package avicit.bdp.dms.das.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.database.ColumnMeta;
import avicit.bdp.common.database.TableMeta;
import avicit.bdp.common.datasource.BaseDataSource;
import avicit.bdp.common.datasource.PrestoDataSource;
import avicit.bdp.common.service.dto.*;
import avicit.bdp.common.service.service.BdpCommonService;
import avicit.bdp.common.service.service.CommonTypeService;
import avicit.bdp.common.service.service.DataSourceService;
import avicit.bdp.common.utils.*;
import avicit.bdp.common.utils.database.DBUtils;
import avicit.bdp.common.utils.database.adapter.BaseDBAdapter;
import avicit.bdp.common.utils.database.adapter.DbAdapter;
import avicit.bdp.common.utils.database.adapter.DbAdapterUtils;
import avicit.bdp.common.utils.enums.CommonTypeEnums;
import avicit.bdp.common.utils.enums.StatusEnums;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.core.enums.DataStateEnum;
import avicit.bdp.core.enums.ModelStoreStatusEnum;
import avicit.bdp.core.enums.TableTypeEnum;
import avicit.bdp.core.poi.util.csv.ExcelUtils;
import avicit.bdp.core.util.json.JSONUtils;
import avicit.bdp.dms.das.dao.BdpDasTableDao;
import avicit.bdp.dms.das.dto.*;
import avicit.bdp.dms.das.utils.LogicExcelChangValue;
import avicit.bdp.dms.das.vo.ColumnInfoVO;
import avicit.bdp.dms.das.vo.PartitionedColumnInfoVO;
import avicit.bdp.dms.das.vo.TableInfoVO;
import avicit.bdp.dms.perm.utils.common.PermCommonService;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.OssClient;
import avicit.platform6.api.system.SysLookupClient;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.modules.system.sysexcelimporthistory.domain.SysExcelImportHistory;
import avicit.platform6.modules.system.sysexcelimporthistory.service.SysExcelImportHistoryService;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.util.PoiCellUtil;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

import static com.google.common.collect.Lists.newArrayList;

/**
 * @author xugb
 */
@Transactional
@Service
public class BdpDasTableService extends BaseService<BdpDasTableDao, BdpTableDTO> {

    @Autowired
    private BdpDasColumnService bdpDasColumnService;
    @Autowired
    private BdpDasLinkService bdpDasLinkService;
    @Autowired
    private BdpDasCategoryService bdpDasCategoryService;
    @Autowired
    private DataSourceService bdpDasDatasourceService;
    @Autowired
    private CommonTypeService commonTypeService;
    @Autowired
    private StorageGroupService storageGroupService;
    @Autowired
    private DataSourceService dataSourceService;
    @Autowired
    private ColumnPartitionedService columnPartitionedService;
    @Autowired
    private BdpDasTableService bdpDasTableService;
    @Autowired
    SysExcelImportHistoryService sysExcelImportHistoryService;
    @Autowired
    OssClient sysFileUploadService;
    @Autowired
    private PermCommonService commonService;
    @Autowired
    private BdpDasTableHistoryService tableHistoryService;
    @Autowired
    private BdpDasColumnHistoryService columnHistoryService;
    @Autowired
    private ColumnPartitionedHistoryService partitionedHistoryService;
    @Autowired
    private ConvertColumnClient convertColumnClient;
    @Autowired
    private BdpCommonService bdpCommonService;

    /**
     * V6平台通用代码
     */
    @Autowired
    private SysLookupClient sysLookupClient;

    private final String[] typeEnum =
            new String[]{
                    "date", "time", "blob", "clob", "text", "timestamp", "date", "datetime", "timestamp(6)"
            };

    private final Integer modelWidth = 240;

    /**
     * 新增对象
     *
     * @param bdpDasTableDTO 保存对象
     * @return String
     */
    @Transactional(rollbackFor = Exception.class)
    public BdpTableDTO insertBdpDasTable(BdpTableDTO bdpDasTableDTO) {

        if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceType())
                && Constants.DB_TYPE_IOTDB.equals(bdpDasTableDTO.getDataSourceType())) {
            String tableName = bdpDasTableDTO.getStorageGroup() + "." + bdpDasTableDTO.getName();
            bdpDasTableDTO.setName(tableName);
            if (!bdpDasTableDTO.getName().startsWith("root.")) {
                throw new BusinessException("存储组应以'root.'开头");
            }
        }
        Map<String, Object> map = Maps.newHashMap();
        bdpDasTableDTO.setId(ComUtil.getId());
        bdpDasTableDTO.setStatus(DataStateEnum.UNDER_EDITING.getCode());
        bdpDasTableDTO.setTableVersion("1.0");
        bdpDasTableDTO.setSecretLevel(bdpCommonService.getMinSecretLevel());

        try {
            insertSelective(bdpDasTableDTO);
            // 记录日志
            BdpLogUtil.log4Insert(bdpDasTableDTO);
            return bdpDasTableDTO;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 修改对象全部字段
     *
     * @param bdpDasTableDTO 修改对象
     * @return int
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> updateBdpDasTable(BdpTableDTO bdpDasTableDTO) {

        if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceType())
                && Constants.DB_TYPE_IOTDB.equals(bdpDasTableDTO.getDataSourceType())) {
            String tableName = bdpDasTableDTO.getStorageGroup() + "." + bdpDasTableDTO.getName();
            bdpDasTableDTO.setName(tableName);
            if (!bdpDasTableDTO.getName().startsWith("root.")) {
                throw new BusinessException("存储组应以'root.'开头");
            }
        }
        Map<String, Object> map = Maps.newHashMap();

        try {
            /******************************新加判断表名特殊字符以及字段关键字**************/
            MutablePair mutablePair = TableUtils.checkTableInfoValid(bdpDasTableDTO);
            Boolean flag = (Boolean) mutablePair.getLeft();
            if (!flag) {
                throw new BusinessException((String) mutablePair.getRight());
            }
            /**************修改数据源类型：删除字段重新添加；无修改类型，需要比对*************/
            List<BdpColumnDTO> columnDTOList = bdpDasTableDTO.getColumnList();
            BdpTableDTO oldTable = this.selectByPrimaryKey(bdpDasTableDTO.getId());
            if (oldTable.getType() == TableTypeEnum.TABLE_PHYSICAL.getCode()
                    && !bdpDasTableDTO.getDataSourceType().equals(oldTable.getDataSourceType())) {
                // 重置字段
                resetColumns(bdpDasTableDTO);
            } else {
                // 对比字段处理
                handleColumns(bdpDasTableDTO);
            }
            /*************************************2022/9/14重新计算模型高度*****************************************/
            Integer modelHeight = columnDTOList.size() * 30 + 45;
            bdpDasTableDTO.setModelHeight(modelHeight);
            /********************************************************************************************/

            // 更新表数据
            BdpTableDTO table = getUpdateDto(bdpDasTableDTO);

            updateByPrimaryKey(table);

            // 处理iotdb的存储组,如果数据库不存在，则默认保存
            if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceType())
                    && Constants.DB_TYPE_IOTDB.equals(bdpDasTableDTO.getDataSourceType())) {
                StorageGroupDTO query = new StorageGroupDTO();
                query.setName(bdpDasTableDTO.getStorageGroup());
                List<StorageGroupDTO> storageList = storageGroupService.selectList(query);
                if (storageList.isEmpty()) {
                    query.setId(ComUtil.getId());
                    storageGroupService.insertStorageGroup(query);
                } else {
                    // 更新时间
                    storageGroupService.updateStorageGroup(storageList.get(0));
                }
            }

            BdpColumnDTO query = new BdpColumnDTO();
            query.setTableId(bdpDasTableDTO.getId());
            List<BdpColumnDTO> columnList =
                    bdpDasColumnService.selectList(query).stream()
                            .sorted(Comparator.comparing(BdpColumnDTO::getOrderBy))
                            .collect(Collectors.toList());
            // 落库
            /**
             * if (bdpDasTableDTO.getType()!= null && (bdpDasTableDTO.getType() ==
             * 5||bdpDasTableDTO.getType() == 1)) { //物理模型和开发工作台
             * insertDataBase(bdpDasTableDTO.getId(),bdpDasTableDTO.getDataSourceId()); }*
             */
            map.put("tableId", bdpDasTableDTO.getId());
            map.put("columnList", columnList);

            return map;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 修改字段处理
     *
     * @param bdpDasTableDTO
     */
    private void handleColumns(BdpTableDTO bdpDasTableDTO) {
        // 1.查询原字段
        List<String> columnIds = bdpDasColumnService.selectIdByTableId(bdpDasTableDTO.getId());
        // 2.修改后字段
        List<BdpColumnDTO> columnDTOList = bdpDasTableDTO.getColumnList();
        for (BdpColumnDTO bdpColumnDTO : columnDTOList) {
            // 3.如果没id 新增字段
            if (StringUtils.isBlank(bdpColumnDTO.getId())) {
                bdpColumnDTO.setId(ComUtil.getId());
                bdpColumnDTO.setTableId(bdpDasTableDTO.getId());
                bdpDasColumnService.insert(bdpColumnDTO);
            } else {
                // 4.有id则修改
                bdpDasColumnService.updateBdpDasColumn(bdpColumnDTO);
                columnIds.remove(bdpColumnDTO.getId());
            }
        }
        // 5.不匹配的id，则删除
        if (CollectionUtils.isNotEmpty(columnIds)) {
            for (String columnId : columnIds) {
                bdpDasColumnService.deleteByPrimaryKey(columnId);
                bdpDasLinkService.deleteLinkByColumnId(columnId);
            }
        }
        /******分区字段处理，逻辑同上******/
        List<ColumnPartitionedDTO> columnPartitionedDTOList = bdpDasTableDTO.getPartitionedColumnList();
        if (CollectionUtils.isNotEmpty(columnPartitionedDTOList)) {
            List<String> parColumnIds =
                    columnPartitionedService.selectIdByTableId(bdpDasTableDTO.getId());
            for (ColumnPartitionedDTO partitionedDTO : columnPartitionedDTOList) {
                if (StringUtils.isBlank(partitionedDTO.getId())) {
                    partitionedDTO.setId(ComUtil.getId());
                    partitionedDTO.setTableId(bdpDasTableDTO.getId());
                    columnPartitionedService.insert(partitionedDTO);
                } else {
                    columnPartitionedService.updateByPrimaryKey(partitionedDTO);
                    parColumnIds.remove(partitionedDTO.getId());
                }
            }
            if (CollectionUtils.isNotEmpty(parColumnIds)) {
                for (String parColumnId : parColumnIds) {
                    columnPartitionedService.deleteByPrimaryKey(parColumnId);
                }
            }
        }
    }

    /**
     * 物理模型切換數據源，字段需要删除再新增
     *
     * @param bdpDasTableDTO
     */
    private void resetColumns(BdpTableDTO bdpDasTableDTO) {
        bdpDasColumnService.deleteBdpDasColumnByTableId(bdpDasTableDTO.getId());
        bdpDasLinkService.deleteLinkByTableId(bdpDasTableDTO.getId());
        // 字段处理
        List<BdpColumnDTO> columnDTOList = bdpDasTableDTO.getColumnList();
        // 处理iotdb Time字段
        if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceType())
                && Constants.DB_TYPE_IOTDB.equals(bdpDasTableDTO.getDataSourceType())) {
            BdpColumnDTO bdpDasColumnDTO = new BdpColumnDTO();
            bdpDasColumnDTO.setTableId(bdpDasTableDTO.getId());
            bdpDasColumnDTO.setName("Time");
            bdpDasColumnDTO.setCnName("Time");
            bdpDasColumnDTO.setModifyable(0);
            bdpDasColumnDTO.setColumnType("timestamp");
            bdpDasColumnDTO.setOrderBy(0);
            bdpDasColumnDTO.setNullable(1);
            columnDTOList.add(0, bdpDasColumnDTO);
        }
        if (columnDTOList != null && columnDTOList.size() > 0) {
            BdpColumnDTO firstColumn = columnDTOList.get(0);
            if ("time".equals(firstColumn.getName().toLowerCase()) && firstColumn.getOrderBy() == 0) {
                for (BdpColumnDTO bdpDasColumnDTO : columnDTOList) {
                    bdpDasColumnDTO.setOrderBy(bdpDasColumnDTO.getOrderBy() + 1);
                }
            }
            // 循环新的字段列表
            for (BdpColumnDTO bdpDasColumnDTO : columnDTOList) {
                if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceType())
                        && Constants.DB_TYPE_IOTDB.equals(bdpDasTableDTO.getDataSourceType())
                        && "time".equals(bdpDasColumnDTO.getName().toLowerCase())
                        && !"timestamp".equals(bdpDasColumnDTO.getColumnType())) {
                    throw new BusinessException("Time为 iotdb 自动创建列，不可手动添加");
                }
                // 给字段赋值表ID
                bdpDasColumnDTO.setTableId(bdpDasTableDTO.getId());
                bdpDasColumnService.insertBdpDasColumn(bdpDasColumnDTO);
            }
        }

        /***********************************分区字段处理**************************************************/
        if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceType())
                && Constants.DB_TYPE_HIVE.equals(bdpDasTableDTO.getDataSourceType())) {
            List<ColumnPartitionedDTO> partitionedDTOList = bdpDasTableDTO.getPartitionedColumnList();
            if (CollectionUtils.isNotEmpty(partitionedDTOList)) {
                columnPartitionedService.deleteByTableId(bdpDasTableDTO.getId());
                int partitionedOrder = 1;
                for (ColumnPartitionedDTO columnPartitionedDTO : partitionedDTOList) {
                    columnPartitionedDTO.setId(ComUtil.getId());
                    columnPartitionedDTO.setTableId(bdpDasTableDTO.getId());
                    columnPartitionedDTO.setOrderBy(partitionedOrder);
                    partitionedOrder++;
                    columnPartitionedService.insert(columnPartitionedDTO);
                }
            }
        }
    }

    /**
     * 在落库后，需要调用此方法，清空修改名称的状态
     *
     * @param tableId 模型ID
     */
    public void deleteTableNameOld(String tableId) {
        bdpDasColumnService.updateColumnNameOldNull(tableId);
        this.mapper.updateTableNameOldNull(tableId);
    }

    /**
     * 比较列
     *
     * @param newTable    newTable
     * @param oldTable    oldTable
     * @param storeStatus 落库状态
     * @return 比对结果
     */
    private boolean compareTableDTO(BdpTableDTO newTable, BdpTableDTO oldTable, Integer storeStatus) {
        if (oldTable == null) {
            return true;
        } else if (!newTable.getName().equalsIgnoreCase(oldTable.getName())) {
            // 判断已落库的表名，如果修改，则保留旧名，便于表修改
            if (storeStatus.equals(ModelStoreStatusEnum.STORE_STATUS_SAVED.ordinal())
                    || storeStatus.equals(ModelStoreStatusEnum.STORE_STATUS_EDITED.ordinal())) {
                if (StringUtils.isBlank(oldTable.getNameOld())) {
                    newTable.setNameOld(oldTable.getName());
                } else {
                    newTable.setNameOld(oldTable.getNameOld());
                }
            }
            return true;
        } else if (compareValue(newTable.getDataSourceId(), oldTable.getDataSourceId())) {
            return true;
        } else if (compareValue(newTable.getStorageGroup(), oldTable.getStorageGroup())) {
            return true;
        } else if (compareValue(newTable.getRemark(), oldTable.getRemark())) {
            return true;
        }
        return false;
    }

    /**
     * 比较列
     *
     * @param newColumn   新列
     * @param oldColumn   旧列
     * @param storeStatus 落库状态
     * @return 比对结果
     */
    private boolean compareColumnDTO(
            BdpColumnDTO newColumn, BdpColumnDTO oldColumn, Integer storeStatus) {
        if (oldColumn == null) {
            return true;
        } else if (!newColumn.getName().equalsIgnoreCase(oldColumn.getName())) {
            // 判断已落库的字段名，如果修改，则保留旧名，便于表修改
            if (storeStatus.equals(ModelStoreStatusEnum.STORE_STATUS_SAVED.ordinal())) {
                if (StringUtils.isBlank(oldColumn.getNameOld())) {
                    newColumn.setNameOld(oldColumn.getName());
                } else {
                    newColumn.setNameOld(oldColumn.getNameOld());
                }
            }
            return true;
        } else if (compareValue(newColumn.getColumnType(), oldColumn.getColumnType())) {
            return true;
        } else if (compareValue(newColumn.getColumnLength(), oldColumn.getColumnLength())) {
            return true;
        } else if (compareValue(newColumn.getColumnPrecision(), oldColumn.getColumnPrecision())) {
            return true;
        } else if (compareIntegerValue(newColumn.getPrimaryKey(), oldColumn.getPrimaryKey())) {
            return true;
        } else if (compareIntegerValue(newColumn.getNullable(), oldColumn.getNullable())) {
            return true;
        } else if (compareIntegerValue(newColumn.getUniqueKey(), oldColumn.getUniqueKey())) {
            return true;
        } else if (compareValue(newColumn.getRemark(), oldColumn.getRemark())) {
            return true;
        }
        return false;
    }

    /**
     * 比较integer类型的primarykey、nullable，uniquekey，
     *
     * @param newObj
     * @param oldObj
     * @return
     */
    private boolean compareIntegerValue(Object newObj, Object oldObj) {
        if (newObj == null && oldObj != null && oldObj.equals(1)) {
            return true;
        } else if (newObj != null && newObj.equals(1) && oldObj == null) {
            return true;
        } else if (newObj == null && oldObj == null) {
            return false;
        } else {
            return newObj.equals(oldObj);
        }
    }

    /**
     * 比较其他
     *
     * @param newObj newObj
     * @param oldObj oldObj
     * @return 比较结果
     */
    private boolean compareValue(Object newObj, Object oldObj) {
        if (newObj == null && oldObj != null) {
            return true;
        } else if (newObj != null && oldObj == null) {
            return true;
        } else if (newObj == null && oldObj == null) {
            return false;
        } else {
            return newObj.equals(oldObj);
        }
    }

    /**
     * 内部方法，获取修改的dto对象
     *
     * @param bdpDasTableDTO 数据表对象
     * @return 数据表对象
     */
    private BdpTableDTO getUpdateDto(BdpTableDTO bdpDasTableDTO) {
        BdpTableDTO oldDTO = selectByPrimaryKey(bdpDasTableDTO.getId());
        if (oldDTO == null) {
            throw new BusinessException("数据不存在");
        }
        // 记录日志
        BdpLogUtil.log4Update(bdpDasTableDTO, oldDTO);
        oldDTO.setName(bdpDasTableDTO.getName());
        oldDTO.setCnName(bdpDasTableDTO.getCnName());
        oldDTO.setRemark(bdpDasTableDTO.getRemark());
        oldDTO.setLayerId(bdpDasTableDTO.getLayerId());
        if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceType())) {
            if (Constants.DB_TYPE_HIVE.equals(bdpDasTableDTO.getDataSourceType())) {
                oldDTO.setDataStorageFormat(bdpDasTableDTO.getDataStorageFormat());
            }
            oldDTO.setStorageGroup(bdpDasTableDTO.getStorageGroup());
            oldDTO.setDataSourceType(bdpDasTableDTO.getDataSourceType());
            oldDTO.setDataSourceId(bdpDasTableDTO.getDataSourceId());
        }
        if (StringUtils.isNotBlank(bdpDasTableDTO.getSourceTableId())) {
            oldDTO.setSourceTableId(bdpDasTableDTO.getSourceTableId());
            if (TableTypeEnum.TABLE_LOGIC.getCode() == bdpDasTableDTO.getSourceType()) {//如果是逻辑模型返回模型名称
                BdpTableDTO sourceDTO = this.selectByPrimaryKey(bdpDasTableDTO.getSourceTableId());
                oldDTO.setSourceName(sourceDTO.getName());
            }
        } else {
            oldDTO.setSourceTableId(null);
        }
        if (bdpDasTableDTO.getSourceType() != null) {
            oldDTO.setSourceType(bdpDasTableDTO.getSourceType());
        } else {
            oldDTO.setSourceType(9); //默认
        }
        /**********************************2022/9/14***********************************************/
        // 修改分类
        if (StringUtils.isNotBlank(bdpDasTableDTO.getTypeId())
                && (!oldDTO.getTypeId().equals(bdpDasTableDTO.getTypeId()))) {
            // 判断分类是否存在重名模型
            boolean isExitModel =
                    this.isExitModel(bdpDasTableDTO.getTypeId(), bdpDasTableDTO.getName(), oldDTO.getType());
            if (isExitModel) {
                throw new BusinessException("选择分类下存在相同名称模型，请修改！");
            }
            // 删除连线信息
            bdpDasLinkService.deleteLinkByTableId(bdpDasTableDTO.getId());
            oldDTO.setTypeId(bdpDasTableDTO.getTypeId());
            // 计算模型位置
            Map<String, Object> map = new HashMap<>();
            countLocation(map, bdpDasTableDTO.getTypeId());
            // 横坐标
            oldDTO.setModelY(MapUtils.getInteger(map, "modelY"));
            oldDTO.setModelX(MapUtils.getInteger(map, "modelX"));
        }
        if (bdpDasTableDTO.getModelHeight() != null) {
            oldDTO.setModelHeight(bdpDasTableDTO.getModelHeight());
        }
        oldDTO.setModelWidth(
                bdpDasTableDTO.getModelWidth() == null ? modelWidth : bdpDasTableDTO.getModelWidth());
        /**********************************2022/9/14_end***********************************************/
        oldDTO.setSecretLevel(bdpDasTableDTO.getSecretLevel());
        return oldDTO;
    }

    /**
     * 工作台表管理修改表
     *
     * @param bdpDasTableDTO
     * @return
     */
    private BdpTableDTO getUpdateProjectTableDto(BdpTableDTO bdpDasTableDTO) {
        BdpTableDTO oldDTO = selectByPrimaryKey(bdpDasTableDTO.getId());
        if (oldDTO == null) {
            throw new BusinessException("数据不存在");
        }
        // 记录日志
        BdpLogUtil.log4Update(bdpDasTableDTO, oldDTO);
        oldDTO.setName(bdpDasTableDTO.getName());
        oldDTO.setCnName(bdpDasTableDTO.getCnName());
        oldDTO.setRemark(bdpDasTableDTO.getRemark());

        // 修改分类
        String projectId = bdpDasTableDTO.getProjectId();
        String typeId = bdpDasTableDTO.getTypeId();
        if (StringUtils.isNotBlank(typeId)) {
            if (StringUtils.isBlank(projectId)) {
                throw new BusinessException("参数【projectId】不能为空");
            }
            this.mapper.updateProjectTableTypeId(projectId, bdpDasTableDTO.getId(), typeId);
        }

        if (Constants.DB_TYPE_HIVE.equals(bdpDasTableDTO.getDataSourceType())) {
            oldDTO.setDataStorageFormat(bdpDasTableDTO.getDataStorageFormat());
        }
        oldDTO.setDataSourceType(bdpDasTableDTO.getDataSourceType());
        if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceId())) {
            oldDTO.setDataSourceId(bdpDasTableDTO.getDataSourceId());
        }
        oldDTO.setStorageGroup(bdpDasTableDTO.getStorageGroup());
        oldDTO.setNameOld(bdpDasTableDTO.getNameOld());
        return oldDTO;
    }

    /**
     * 判断在新分类下是否存在重名
     *
     * @param typeId
     * @param name
     * @return
     */
    private boolean isExitModel(String typeId, String name, Integer type) {
        List<BdpTableDTO> list = this.mapper.selectByNameAndTypeId(typeId, name, type);
        if (CollectionUtils.isNotEmpty(list)) {
            return true;
        }
        return false;
    }

    /**
     * 删除数据
     *
     * @param map
     */
    @Transactional(rollbackFor = Exception.class)
    public String deleteBdpDasTableByIds(Map<String, Object> map) {
        String id = MapUtils.getString(map, "id", "");
        Integer delDB = MapUtils.getInteger(map, "delDB", 0);
        if (StringUtils.isBlank(id)) {
            return "删除失败！传入的参数主键为null";
        }
        // 查询引用模型的数据空间
        List<String> projectNames = this.mapper.getProjectNamesByTableId(id);
        if (CollectionUtils.isNotEmpty(projectNames)) {
            StringBuffer sb = new StringBuffer();
            for (String str : projectNames) {
                sb.append(str).append("、");
            }
            String projectNameStr = sb.deleteCharAt(sb.length() - 1).toString();
            return projectNameStr + "引用了本模型，请先移除空间里模型引用!";
        }
        // 记录日志
        BdpTableDTO bdpDasTableDTO = selectByPrimaryKey(id);
        if (bdpDasTableDTO == null) {
            return "删除失败！对象不存在";
        }
        // 删除关联字段的信息
        bdpDasColumnService.deleteBdpDasColumnByTableId(id);
        // 删除关系线信息
        bdpDasLinkService.deleteLinkByTableId(id);
        deleteByPrimaryKey(id);
        BdpLogUtil.log4Delete(bdpDasTableDTO);
        if (bdpDasTableDTO.getType() != null
                && TableTypeEnum.TABLE_PHYSICAL.getCode() == bdpDasTableDTO.getType()
                && DataStateEnum.PUBLISHED.getCode() == bdpDasTableDTO.getStatus()
                && 1 == delDB) {
            Connection conn = null;
            String datasourceId = bdpDasTableDTO.getDataSourceId();
            DataSourceDTO dataSourceDTO = bdpDasDatasourceService.selectByPrimaryKey(datasourceId);
            BaseDataSource dbSource = DBUtils.getBaseDataSource(dataSourceDTO);
            TableMeta tableMeta = new TableMeta();
            BeanUtils.copyProperties(bdpDasTableDTO, tableMeta);
            try {
                conn = DBUtils.buildConnection(dataSourceDTO);
                DbAdapter adapter = DbAdapterUtils.getDbAdapter(dataSourceDTO.getDatasourceType());
                adapter.dropDataTable(tableMeta.getName(), dbSource);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw new BusinessException("数据源连接失败");
            } finally {
                DBUtils.closeResource(conn, null, null);
            }
        }
        return "";
    }

    //逻辑模型批量删除
    public Boolean batchDelete(String ids) {
        CheckParaUtils.checkStringValidity(ids, logger, "没有传入待删除的ID");
        String[] idArr = ids.split(Constants.COMMA);
        for (String id : idArr) {
            BdpTableDTO bdpTableDTO = this.selectByPrimaryKey(id);
            CheckParaUtils.checkDbObjectValidity(
                    bdpTableDTO, logger, String.format("没有查到数据，请确保id:%s的数据是否存在", id));

            //删除字段
            // 删除关联字段的信息
            bdpDasColumnService.deleteBdpDasColumnByTableId(id);
            // 删除关系线信息
            bdpDasLinkService.deleteLinkByTableId(id);
            this.mapper.deleteByPrimaryKey(id);

            //查询历史版本
            BdpTableHistoryDTO queryDTO = new BdpTableHistoryDTO();
            queryDTO.setTableId(id);
            List<BdpTableHistoryDTO> tableHistorys = tableHistoryService.selectList(queryDTO);

            if (CollectionUtils.isNotEmpty(tableHistorys)) {
                for (BdpTableHistoryDTO tableHistory : tableHistorys) {
                    columnHistoryService.deleteByTableId(tableHistory.getId());
                    tableHistoryService.deleteByPrimaryKey(tableHistory.getId());
                }
            }

            // 记录日志
            BdpLogUtil.log4Delete(bdpTableDTO);
        }
        return true;
    }

    /**
     * 保存
     *
     * @param tables tables
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveModelImage(List<BdpTableDTO> tables) {
        try {
            for (BdpTableDTO table : tables) {
                BdpTableDTO bdpDasTableDTO = selectByPrimaryKey(table.getId());
                // BdpLogUtil.log4Update(table,bdpDasTableDTO);
                bdpDasTableDTO.setModelX(table.getModelX());
                bdpDasTableDTO.setModelY(table.getModelY());
                bdpDasTableDTO.setModelHeight(table.getModelHeight());
                bdpDasTableDTO.setModelWidth(table.getModelWidth());
                updateByPrimaryKey(bdpDasTableDTO);
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 判断表名是否重复
     *
     * @param tableId   模型ID
     * @param tableName 模型英名称【转换为小写】
     * @param typeId    分类ID
     * @return 是否重复
     */
    @Transactional(readOnly = true)
    public Integer isSameName(String tableId, String tableName, String typeId, Integer type) {
        int flag = 0;
        List<BdpTableDTO> list = mapper.selectByNameAndTypeId(typeId, tableName.toLowerCase(), type);
        if (CollectionUtils.isNotEmpty(list)) {
            if (StringUtils.isEmpty(tableId)) {
                return 1;
            }
            for (BdpTableDTO dto : list) {
                if (!dto.getId().equals(tableId)) {
                    flag = 1;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * 新的落库方法
     *
     * @param modelIds     模型列表
     * @param datasourceId 数据源ID
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, List<String>> insertDataBase(String modelIds, String datasourceId) {
        Connection conn = null;
        DataSourceDTO dataSourceDTO = bdpDasDatasourceService.selectByPrimaryKey(datasourceId);
        BaseDataSource dbSource = DBUtils.getBaseDataSource(dataSourceDTO);
        Map<String, List<String>> result = new HashMap<>(3);
        List<String> successList = new LinkedList<>();
        List<String> errorList = new LinkedList<>();
        List<String> errorInfoList = new LinkedList<>();
        result.put("successList", successList);
        result.put("errorList", errorList);
        result.put("errorInfoList", errorInfoList);
        try {

            conn = DBUtils.buildConnection(dataSourceDTO);
            DbAdapter adapter = DbAdapterUtils.getDbAdapter(dataSourceDTO.getDatasourceType());
            String[] modelIdList = modelIds.split(Constants.COMMA);
            List<String> tableNameList = newArrayList();
            for (String modelId : modelIdList) {
                // 表信息
                BdpTableDTO dataTable = selectByPrimaryKey(modelId);
                // 字段信息
                BdpColumnDTO columnQuery = new BdpColumnDTO();
                columnQuery.setTableId(modelId);
                List<BdpColumnDTO> columnInfoList =
                        bdpDasColumnService.selectList(columnQuery).stream()
                                .sorted(Comparator.comparing(BdpColumnDTO::getOrderBy))
                                .collect(Collectors.toList());

                List<ColumnMeta> columnMetaList = newArrayList();
                if (CollectionUtils.isNotEmpty(columnInfoList)) {
                    dataTable.setColumnList(columnInfoList);
                    for (BdpColumnDTO bdpDasColumnDTO : columnInfoList) {
                        if (Constants.DB_TYPE_IOTDB.equals(dataTable.getDataSourceType())
                                && "time".equals(bdpDasColumnDTO.getName().toLowerCase())) {
                        } else {
                            ColumnMeta columnMeta = new ColumnMeta();
                            BeanUtils.copyProperties(bdpDasColumnDTO, columnMeta);
                            columnMetaList.add(columnMeta);
                        }
                    }
                }

                // 分区字段信息
                ColumnPartitionedDTO pColumnQuery = new ColumnPartitionedDTO();
                pColumnQuery.setTableId(modelId);
                List<ColumnPartitionedDTO> pColumns =
                        columnPartitionedService.selectList(pColumnQuery).stream()
                                .sorted(Comparator.comparing(ColumnPartitionedDTO::getOrderBy))
                                .collect(Collectors.toList());
                List<ColumnMeta> pColumnMetaList = newArrayList();
                if (Constants.DB_TYPE_HIVE.equals(dataSourceDTO.getDatasourceType())
                        && CollectionUtils.isNotEmpty(pColumns)) {
                    for (ColumnPartitionedDTO pColumn : pColumns) {
                        ColumnMeta columnMeta = new ColumnMeta();
                        BeanUtils.copyProperties(pColumn, columnMeta);
                        pColumnMetaList.add(columnMeta);
                    }
                }

                try {
                    String oldName = dataTable.getNameOld();
                    TableMeta tableMeta = new TableMeta();
                    BeanUtils.copyProperties(dataTable, tableMeta);

                    // 如果为presto，需知类型
                    if (Constants.DB_TYPE_PRESTO.equals(dataTable.getDataSourceType())) {
                        PrestoDataSource prestoDataSource =
                                (PrestoDataSource) DBUtils.getBaseDataSource(dataSourceDTO);
                        String dbType = prestoDataSource.getType();
                        tableMeta.setDbType(dbType);
                    }

                    /******************1、修改表名**************************************************/
                    if (StringUtils.isNotBlank(oldName)) {
                        if (adapter.isExistTable(tableMeta.getName(), conn)) {
                            errorList.add(dataTable.getName());
                            errorInfoList.add(dataTable.getName() + "落库失败：表名已存在");
                            continue;
                        }
                        // 修改表名
                        String newName = dataTable.getName();
                        tableMeta.setName(oldName);
                        adapter.renameDataTable(conn, tableMeta, newName);
                        tableMeta.setName(newName);
                    }

                    /*****************2、判断是否存在物理表 不存在直接创建****************************/
                    if (!adapter.isExistTable(tableMeta.getName(), conn)) {
                        tableMeta.setColumnMetaData(columnMetaList);
                        if (Constants.DB_TYPE_HIVE.equals(dataSourceDTO.getDatasourceType())
                                && CollectionUtils.isNotEmpty(pColumnMetaList)) {
                            tableMeta.setPcolumnMetaData(pColumnMetaList);
                        }
                        adapter.createDataTable(tableMeta, conn);

                    } else {
                        /*****************3、存在物理表判断是否存在数据,不存在删除创建，存在对比************/
                        // 判断物理表是否有数据
                        if (tableData(modelId) == 0) {
                            adapter.dropDataTable(tableMeta.getName(), dbSource);
                            if (Constants.DB_TYPE_HIVE.equals(dataSourceDTO.getDatasourceType())
                                    && CollectionUtils.isNotEmpty(pColumnMetaList)) {
                                tableMeta.setPcolumnMetaData(pColumnMetaList);
                            }
                            tableMeta.setColumnMetaData(columnMetaList);
                            adapter.createDataTable(tableMeta, conn);
                        } else {
                            /**************2023/4/21  存在数据不可以落库**********************/
                            errorList.add(modelId);
                            errorInfoList.add(dataTable.getName() + "落库失败：数据表存在数据");
                            // 修改表信息
                            // adapter.alterDataTable(conn, tableMeta);
                            // 修改表结构
                            // updateColumnInfo(adapter, datasourceId, dataTable, columnInfoList, conn);
                        }
                    }
                    deleteTableNameOld(modelId);
                    // 修改模型落库状态
                    dataTable.setStatus(DataStateEnum.PUBLISHED.getCode());
                    // dataTable.setStoreStatus(ModelStoreStatusEnum.STORE_STATUS_SAVED.ordinal());
                    // 落库后修改数据源未落库选择的数据源
                    dataTable.setDataSourceId(datasourceId);
                    // 落库后修改字段是否可修改状态
                    updateByPrimaryKey(dataTable);
                    // 落库后修改字段是否可修改
                    bdpDasColumnService.updateModifyAble(modelId);
                    successList.add(modelId);

                    // 用于记录日志
                    tableNameList.add(dataTable.getName());
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                    errorList.add(modelId);
                    errorInfoList.add(dataTable.getName() + "落库失败：执行脚本出错--" + e.getMessage());
                }
            }
            String tableNames = StringUtils.join(tableNameList, ",");
            String logTitle =
                    "模型落库：数据源【" + dataSourceDTO.getDatasourceName() + "】，模型：【" + tableNames + "】";
            // 记录日志
            BdpLogUtil.log("数据模型模块", logTitle, PlatformConstant.OpType.update);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BusinessException("数据源连接失败");
        } finally {
            DBUtils.closeResource(conn, null, null);
        }
        return result;
    }

    private void updateColumnInfo(
            DbAdapter adapter,
            String datasourceId,
            BdpTableDTO dataTable,
            List<BdpColumnDTO> columnInfoList,
            Connection conn)
            throws Exception {

        List<ColumnMeta> columnMetaList =
                bdpDasDatasourceService.getColumnList(datasourceId, dataTable.getName());
        Map<String, ColumnMeta> columnMap = Maps.newHashMap();
        TableMeta tableMeta = new TableMeta();
        BeanUtils.copyProperties(dataTable, tableMeta);

        if (columnMetaList != null && columnMetaList.size() > 0) {
            for (ColumnMeta columnMeta : columnMetaList) {
                columnMap.put(columnMeta.getName().toLowerCase(), columnMeta);
            }
            for (BdpColumnDTO bdpDasColumnDTO : columnInfoList) {
                ColumnMeta columnMeta = new ColumnMeta();
                BeanUtils.copyProperties(bdpDasColumnDTO, columnMeta);

                // 判断是否为该名称字段
                String colOldName = bdpDasColumnDTO.getNameOld();
                if (StringUtils.isNotBlank(colOldName)) {
                    String newName = bdpDasColumnDTO.getName();
                    columnMeta.setName(colOldName);
                    adapter.renameDataColumn(conn, tableMeta, columnMeta, newName);
                    columnMeta.setName(newName);

                    ColumnMeta meta = columnMap.remove(colOldName.toLowerCase());
                    // 暂时删除
          /*if (meta != null) {
              if (validateType(meta)) {
                  adapter.alterDataColumn(conn, tableMeta, columnMeta);
              }
          }*/
                } else {
                    ColumnMeta meta = columnMap.remove(bdpDasColumnDTO.getName().toLowerCase());
                    if (meta != null) {
            /*if (validateType(meta)) {
                adapter.alterDataColumn(conn, tableMeta, columnMeta);
            }*/
                    } else {
                        adapter.createDataColumn(conn, tableMeta, columnMeta);
                    }
                }
            }
            if (!columnMap.isEmpty()) {
                /**************presto连接hive也不允许删除***************/
                if (Constants.DB_TYPE_PRESTO.equals(dataTable.getDataSourceType())) {
                    DataSourceDTO dataSourceDTO = dataSourceService.selectByPrimaryKey(datasourceId);
                    PrestoDataSource baseDataSource =
                            (PrestoDataSource) DBUtils.getBaseDataSource(dataSourceDTO);
                    if (Constants.DB_TYPE_HIVE.equals(baseDataSource.getType())) {
                        throw new BusinessException("hive表存在数据不允许删除列！");
                    }
                }
                if (Constants.DB_TYPE_HIVE.equals(dataTable.getDataSourceType())) {
                    throw new BusinessException("hive表存在数据不允许删除列！");
                }
                for (String key : columnMap.keySet()) {
                    tableMeta.setColumnMetaData(columnMetaList);
          /*BdpDasColumnDTO bdpDasColumnDTO = new BdpDasColumnDTO();
          bdpDasColumnDTO.setName(key);*/
                    ColumnMeta columnMeta = columnMap.get(key);
                    // BeanUtils.copyProperties(bdpDasColumnDTO, columnMeta);
                    adapter.dropDataColumn(conn, tableMeta, columnMeta);
                    for (ColumnMeta meta : columnMetaList) {
                        if (meta.getName().equals(key)) {
                            columnMetaList.remove(meta);
                            break;
                        }
                    }
                }
            }
        } else {
            dataTable.setColumnList(columnInfoList);
            adapter.createDataTable(tableMeta, conn);
        }
    }

    /**
     * 根据分类ID递归查询所有模型表 注意： 1、根据登录角色进行权限过滤（仅关心查看、编辑权限）
     *
     * @param type
     * @param typeId
     * @param storeStatus
     * @param keyWords
     * @param pageNo
     * @param pageSize
     * @param wordSecretList
     * @return
     */
    public Page<BdpTableDTO> qureyTableListWithPerm(
            List<String> roleIdList,
            Integer type,
            String typeId,
            String layerId,
            Integer storeStatus,
            String keyWords,
            Integer pageNo,
            Integer pageSize,
            List<String> wordSecretList) {
        // step1:根据typeId，获取所有子节点Id
        List<String> typeIdList = new ArrayList<>();
        Map<String, Integer> childNodePermMap = this.bdpDasCategoryService.getChildNodeMapWithPerm(typeId, roleIdList);
        if (childNodePermMap != null && childNodePermMap.size() > 0) {
            typeIdList = childNodePermMap.keySet().stream().collect(Collectors.toList());
        }

        return qureyTableListByCond(type, layerId, storeStatus, keyWords, pageNo, pageSize, typeIdList, childNodePermMap, wordSecretList);
    }

    /**
     * 根据分类ID递归查询所有模型表 注意： 1、根据登录角色进行权限过滤（仅关心查看、数据查看权限）
     *
     * @param roleIdList 角色列表
     * @param type
     * @param typeId
     * @param status
     * @param keyWords
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<BdpTableDTO> qureyTableListWithDataViewPerm(
            List<String> roleIdList,
            Integer type,
            String typeId,
            Integer status,
            String keyWords,
            Integer pageNo,
            Integer pageSize) {
        // step1:根据typeId，获取自身及所有子节点Id，以及节点权限（0：查看、2：数据查看）
        List<String> typeIdList = new ArrayList<>();
        Map<String, Integer> childNodePermMap =
                this.bdpDasCategoryService.getChildNodePermListWithDataViewPerm(typeId, roleIdList);
        if (childNodePermMap != null && childNodePermMap.size() > 0) {
            typeIdList = childNodePermMap.keySet().stream().collect(Collectors.toList());
        }

        return qureyTableListByCond(type, null, status, keyWords, pageNo, pageSize, typeIdList, childNodePermMap, null);
    }

    /**
     * 中间节点节点查询模型图形 注意： 1、数据建模，根据分类节点ID查看模型列表，根据登录角色过滤权限，仅包括查看、编辑权限
     *
     * @param typeId typeId
     * @return 模型图形
     */
    @Transactional(readOnly = true)
    public QueryRespBean<BdpTableDTO> searchMiddleData(
            String typeId,
            Integer type,
            String layerId,
            Integer storeStatus,
            String keyWords,
            Integer pageNo,
            Integer pageSize) {
        QueryRespBean<BdpTableDTO> queryRespBean = new QueryRespBean<>();
        List<String> roleIdList = this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        Page<BdpTableDTO> dataList = qureyTableListWithPerm(roleIdList, type, typeId, layerId, storeStatus, keyWords, pageNo, pageSize, wordSecretList);

        tableConvert(dataList);
        queryRespBean.setResult(dataList);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    /**
     * 按条件分页查询 注意： 1、数据存储-数据查看，查询指定分类（包含自身及所有递归子节点）下模型列表； 2、根据登录角色进行权限过滤(仅关注查看、数据查看权限)
     *
     * @param typeId   末级节点分类Id
     * @param keyWords 查询关键字
     * @param pageNo   当前页
     * @param pageSize 每页大小
     */
    @Transactional(readOnly = true)
    public QueryRespBean<BdpTableDTO> searchMiddleDataList(
            String typeId, String keyWords, Integer pageNo, Integer pageSize) {
        QueryRespBean<BdpTableDTO> queryRespBean = new QueryRespBean<>();
        List<String> roleIdList =
                this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
        Page<BdpTableDTO> dataList =
                qureyTableListWithDataViewPerm(
                        roleIdList,
                        TableTypeEnum.TABLE_PHYSICAL.getCode(),
                        typeId,
                        DataStateEnum.PUBLISHED.getCode(),
                        keyWords,
                        pageNo,
                        pageSize);

        tableConvert(dataList);
        queryRespBean.setResult(dataList);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    @Transactional(readOnly = true)
    public Long selectCountAll() {
        return this.mapper.selectCountAll();
    }

    @Transactional(readOnly = true)
    public QueryRespBean<BdpTableDTO> getListForModel(String typeId, String projectId, String keyWords,
                                                      Integer pageNo, Integer pageSize, String secretLevel) {
        QueryRespBean<BdpTableDTO> queryRespBean = new QueryRespBean<>();
        try {
            List<String> typeIds = commonTypeService.getChildrenIds(CommonTypeEnums.DATATABLE, typeId, projectId);
            if (typeIds == null) {
                typeIds = newArrayList();
            }
            typeIds.add(typeId);
            com.github.pagehelper.PageHelper.startPage(pageNo, pageSize);
            List<String> wordSecretList = new ArrayList<>();
            if (StringUtils.isNotEmpty(secretLevel)) {
                wordSecretList.addAll(this.sysLookupClient.getSecretWordList(secretLevel));
            } else {
                wordSecretList = ThreadContextHelper.getWordSecretList();
            }
            Page<BdpTableDTO> dataList = this.mapper.getListForModel(typeIds, projectId, keyWords, wordSecretList);
            List<BdpTableDTO> tableList = dataList.getResult();
            if (tableList != null && tableList.size() > 0) {
                for (BdpTableDTO dasTableDTO : tableList) {
                    Integer imported = this.mapper.selectImported(projectId, dasTableDTO.getId(), typeIds);
                    dasTableDTO.setImported(imported);
                    if (StringUtils.isNotBlank(dasTableDTO.getDataSourceId())) {
                        DataSourceDTO dataSourceDTO =
                                bdpDasDatasourceService.selectByPrimaryKey(dasTableDTO.getDataSourceId());
                        if (dataSourceDTO != null) {
                            dasTableDTO.setDataSourceName(dataSourceDTO.getDatasourceName());
                        } else {
                            dasTableDTO.setDataSourceName("");
                        }
                    }
                    BdpColumnDTO bdpDasColumnDTO = new BdpColumnDTO();
                    bdpDasColumnDTO.setTableId(dasTableDTO.getId());
                    List<BdpColumnDTO> columnList =
                            bdpDasColumnService.selectList(bdpDasColumnDTO).stream()
                                    .sorted(Comparator.comparing(BdpColumnDTO::getOrderBy))
                                    .collect(Collectors.toList());
                    dasTableDTO.setColumnList(columnList);
                }
            }
            valueConvert(tableList);
            queryRespBean.setResult(dataList);
            BdpLogUtil.log4Query(queryRespBean);
            return queryRespBean;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    private void valueConvert(List<BdpTableDTO> tableList) {
        // 循环组装请求数据
        Map<String, Set<String>> convertFormData = new HashMap<>();
        if (CollectionUtils.isNotEmpty(tableList)) {
            for (BdpTableDTO tableDTO : tableList) {
                BusinessUtil.createConvertSet(convertFormData, Constants.BDP_DATA_SECRET_LEVEL_KEY, tableDTO.getSecretLevel());
            }
            if (convertFormData.size() > 0) {
                // 获取请求结果
                Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
                for (BdpTableDTO tableDTO : tableList) {
                    tableDTO.setSecretLevelName(BusinessUtil.convertFormat(
                            convertResultData, Constants.BDP_DATA_SECRET_LEVEL_KEY, tableDTO.getSecretLevel()));
                }
            }
        }
    }

    /**
     * 工作台新增数据表
     *
     * @param bdpDasTableDTO 新增数据表
     * @return 数据表ID
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> insertDataTable(BdpTableDTO bdpDasTableDTO) {

        if (Constants.DB_TYPE_IOTDB.equals(bdpDasTableDTO.getDataSourceType())) {
            String tableName = bdpDasTableDTO.getStorageGroup() + "." + bdpDasTableDTO.getName();
            bdpDasTableDTO.setName(tableName);
            if (!bdpDasTableDTO.getName().startsWith("root.")) {
                throw new BusinessException("存储组应以'root.'开头");
            }
        }

        Map<String, Object> map = Maps.newHashMap();
        try {
            /******************************新加判断表名特殊字符以及字段关键字**************/
            MutablePair mutablePair = TableUtils.checkTableInfoValid(bdpDasTableDTO);
            Boolean flag = (Boolean) mutablePair.getLeft();
            if (!flag) {
                throw new BusinessException((String) mutablePair.getRight());
            }
            /****************************************************************************/
            if (StringUtils.isBlank(bdpDasTableDTO.getId())) {
                bdpDasTableDTO.setId(ComUtil.getId());
            }

            // 数据开发平台项目建模
            if (bdpDasTableDTO.getType() != null
                    && bdpDasTableDTO.getType() == TableTypeEnum.TABLE_DATA_DEVELOP_MODELING.getCode()) {
                String projectId = bdpDasTableDTO.getProjectId();
                String proTableId = ComUtil.getId();
                String tableId = bdpDasTableDTO.getId();
                String userId = ThreadContextHelper.getUserId();
                if (StringUtils.isBlank(userId)) {
                    userId = "1";
                }
                String userIp = ThreadContextHelper.getIp();
                String orgId = ThreadContextHelper.getOrgId();
                if (StringUtils.isBlank(orgId)) {
                    orgId = "1";
                }

                this.mapper.insertProjectTable(
                        proTableId,
                        projectId,
                        tableId,
                        bdpDasTableDTO.getTypeId(),
                        userId,
                        userIp,
                        new Date(),
                        orgId);
            }

            // 新增字段信息
            List<BdpColumnDTO> columnDTOList = bdpDasTableDTO.getColumnList();
            // 处理iotdb Time字段
            if (Constants.DB_TYPE_IOTDB.equals(bdpDasTableDTO.getDataSourceType())
                    && validateTime(columnDTOList)) {
                BdpColumnDTO bdpDasColumnDTO = new BdpColumnDTO();
                bdpDasColumnDTO.setTableId(bdpDasTableDTO.getId());
                bdpDasColumnDTO.setName("Time");
                bdpDasColumnDTO.setCnName("Time");
                bdpDasColumnDTO.setModifyable(0);
                bdpDasColumnDTO.setColumnType("timestamp");
                bdpDasColumnDTO.setOrderBy(0);
                bdpDasColumnDTO.setNullable(1);
                bdpDasColumnDTO.setPrimaryKey(0);
                bdpDasColumnDTO.setForeignKey(0);
                bdpDasColumnDTO.setUniqueKey(0);
                EntityUtils.setCreateAndUpdateInfo(bdpDasColumnDTO);
                columnDTOList.add(0, bdpDasColumnDTO);
            }
            // 重新修改字段排序
            int orderBy = 1;
            for (BdpColumnDTO column : columnDTOList) {
                //if (StringUtils.isBlank(column.getId())) {
                column.setId(ComUtil.getId());
                //}
                column.setTableId(bdpDasTableDTO.getId());
                String userId = ThreadContextHelper.getUserId();
                if (StringUtils.isBlank(userId)) {
                    userId = "1";
                }
                column.setCreatedBy(userId);
                column.setCreationDate(new Date());
                column.setOrderBy(orderBy);
                column.setModifyable(1);
                EntityUtils.setCreateAndUpdateInfo(column);
                orderBy++;
            }
            if (CollectionUtils.isNotEmpty(columnDTOList)) {
                validColumnName(columnDTOList);
                // 批量添加列
                batchHandleColumn(null, columnDTOList);
            }

            // 分区字段处理
            int pOrderBy = 1;
            List<ColumnPartitionedDTO> partitionedDTOS = bdpDasTableDTO.getPartitionedColumnList();
            if (CollectionUtils.isNotEmpty(partitionedDTOS)) {
                for (ColumnPartitionedDTO partitionedDTO : partitionedDTOS) {
                    //if (StringUtils.isBlank(partitionedDTO.getId())) {
                    partitionedDTO.setId(ComUtil.getId());
                    //}
                    partitionedDTO.setTableId(bdpDasTableDTO.getId());
                    String userId = ThreadContextHelper.getUserId();
                    if (StringUtils.isBlank(userId)) {
                        userId = "1";
                    }
                    partitionedDTO.setCreatedBy(userId);
                    partitionedDTO.setCreationDate(new Date());
                    partitionedDTO.setOrderBy(pOrderBy);
                    pOrderBy++;
                    columnPartitionedService.insert(partitionedDTO);
                }
            }
            if (bdpDasTableDTO.getType() != null
                    && bdpDasTableDTO.getType() == TableTypeEnum.TABLE_PHYSICAL.getCode() && bdpDasTableDTO.getSourceType() == 3) {//如果是物理模型导入数据表
                bdpDasTableDTO.setStatus(DataStateEnum.PUBLISHED.getCode());
            } else {
                bdpDasTableDTO.setStatus(DataStateEnum.UNDER_EDITING.getCode());
            }
            insertSelective(bdpDasTableDTO);
            // 记录日志
            BdpLogUtil.log4Insert(bdpDasTableDTO);

            /**************删掉，不自动落库*****************
             *
             * Map<String, List<String>> insMap = insertDataBase(bdpDasTableDTO.getId(),
             * bdpDasTableDTO.getDataSourceId());
             * List<String> errorInfoList = insMap.get("errorInfoList");
             * if (CollectionUtils.isNotEmpty(errorInfoList)) {
             * throw new BusinessException("落库失败:" + errorInfoList.get(0));
             * }*/

            map.put("tableId", bdpDasTableDTO.getId());
            map.put("columnList", columnDTOList);
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }

        return map;
    }

    private boolean validateTime(List<BdpColumnDTO> columnDTOList) {
        boolean flag = true;
        for (BdpColumnDTO bdpDasColumnDTO : columnDTOList) {
            if ("Time".equals(bdpDasColumnDTO.getName())) {
                flag = false;
                break;
            }
        }
        return flag;
    }

    /**
     * 工作台修改数据表
     *
     * @param bdpDasTableDTO 数据表
     * @return 修改信息
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> updateDataTable(BdpTableDTO bdpDasTableDTO) {
        Map<String, Object> map = Maps.newHashMap();
        try {
            // 删除物理表
            /*this.dropTable(bdpDasTableDTO.getId(), bdpDasTableDTO.getDataSourceId());*/
            // 更新表数据
            /***************工作空间表修改内容不同于公共模型 2022/9/16******************/
            updateByPrimaryKey(getUpdateProjectTableDto(bdpDasTableDTO));
            /***************************************************************************/

            // 字段处理
            BdpColumnDTO columnQuery = new BdpColumnDTO();
            columnQuery.setTableId(bdpDasTableDTO.getId());
            bdpDasColumnService.delete(columnQuery);
            // 新增字段信息
            List<BdpColumnDTO> columnDTOList = bdpDasTableDTO.getColumnList();
            // 重新修改字段排序
            int orderBy = 1;
            for (BdpColumnDTO column : columnDTOList) {
                column.setOrderBy(orderBy);
                orderBy++;
            }
            if (CollectionUtils.isNotEmpty(columnDTOList)) {
                validColumnName(columnDTOList);
                // 循环新的字段列表
                for (BdpColumnDTO bdpDasColumnDTO : columnDTOList) {
                    // 给字段赋值表ID
                    bdpDasColumnDTO.setTableId(bdpDasTableDTO.getId());
                    bdpDasColumnService.insertBdpDasColumn(bdpDasColumnDTO);
                }
            }
            map.put("tableId", bdpDasTableDTO.getId());
            map.put("columnList", columnDTOList);
            // this.insertDataBase(bdpDasTableDTO.getId(), bdpDasTableDTO.getDataSourceId());
            return map;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    private void validColumnName(List<BdpColumnDTO> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            Set<String> columnNameSet =
                    list.parallelStream().map(BdpColumnDTO::getName).collect(Collectors.toSet());
            if (list.size() != columnNameSet.size()) {
                throw new BusinessException("列名称有重名，请检查列名称。");
            }
        }
    }

    /**
     * 删除工作台模型新增
     *
     * @param ids       ids
     * @param projectId projectId
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDataTable(String ids, String projectId, Integer delDB) {
        if (StringUtils.isBlank(ids)) {
            throw new BusinessException("删除失败！传入的参数主键为null");
        }
        try {
            String[] idArray = ids.split(Constants.COMMA);
            for (String tableId : idArray) {
                // 查询是否为导入模型
                Integer imported = this.mapper.selectImported(projectId, tableId, null);
                if (imported == 0) {
                    BdpTableDTO bdpDasTableDTO = selectByPrimaryKey(tableId);
                    BdpLogUtil.log4Delete(bdpDasTableDTO);
                    // 删除关联字段的信息
                    bdpDasColumnService.deleteBdpDasColumnByTableId(tableId);
                    deleteByPrimaryKey(tableId);
                    // 删除物理表
                    Connection conn = null;
                    String datasourceId = bdpDasTableDTO.getDataSourceId();
                    DataSourceDTO dataSourceDTO = bdpDasDatasourceService.selectByPrimaryKey(datasourceId);
                    BaseDataSource dbSource = DBUtils.getBaseDataSource(dataSourceDTO);
                    TableMeta tableMeta = new TableMeta();
                    BeanUtils.copyProperties(bdpDasTableDTO, tableMeta);
                    try {
                        conn = DBUtils.buildConnection(dataSourceDTO);
                        DbAdapter adapter = DbAdapterUtils.getDbAdapter(dataSourceDTO.getDatasourceType());
                        adapter.dropDataTable(tableMeta.getName(), dbSource);
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                        throw new BusinessException("数据源连接失败");
                    } finally {
                        DBUtils.closeResource(conn, null, null);
                    }
                }
                this.mapper.deleteProTable(projectId, tableId);
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 查询被导入的表
     *
     * @param projectId 项目空间ID
     * @return 被导入的表集合
     */
    public List<BdpTableDTO> selectListByProjectId(String projectId) {
        return this.mapper.selectListByProjectId(projectId);
    }

    /**
     * 查询空间下面导入数据源中的表
     *
     * @param projectId    projectId
     * @param typeIds      分类ID集合
     * @param type         模型类型
     * @param dbType       数据库类型
     * @param dataSourceId dataSourceId
     * @return 表名集合
     */
    public List<BdpTableDTO> selectTableList(
            String projectId, List<String> typeIds, Integer type, String dbType, String dataSourceId) {
        return this.mapper.selectTableList(projectId, typeIds, type, dbType, null, dataSourceId);
    }

    /**
     * 模型结构比对
     *
     * @param compareDto 模型信息
     * @return 比对结果
     */
    public List<TableCompareResponseDTO> modelCompare(TableCompareRequestDTO compareDto) {
        List<SimpleModelDTO> modelList = compareDto.getModelList();
        // 处理表所属的数据源类型
        if (CollectionUtils.isNotEmpty(modelList)) {
            for (SimpleModelDTO simpleModelDTO : modelList) {
                BdpTableDTO table = selectByPrimaryKey(simpleModelDTO.getTableId());
                simpleModelDTO.setDataSourceType(table.getDataSourceType());
            }
        }
        List<String> typeIdList = new ArrayList<>();
        List<String> tableIdList = Collections.synchronizedList(new ArrayList<>());
        // 缓存数据源查询
        Map<String, DataSourceDTO> dbCache = new ConcurrentHashMap<>(16);
        final Map<String, BdpTableDTO> typeRelatedModelMap = new ConcurrentHashMap<>(16);

        modelList =
                getSimpleModelList(
                        compareDto, modelList, typeIdList, tableIdList, dbCache, typeRelatedModelMap);

        List<TableCompareResponseDTO> response =
                Collections.synchronizedList(new ArrayList<>(modelList.size()));
        if (CollectionUtils.isEmpty(modelList)) {
            return response;
        }

        // 查询模型相关的所有列数据
        Map<String, List<BdpColumnDTO>> columnRelatedMap = new HashMap<>(16);
        List<BdpColumnDTO> bdpDasColumnDTOList = bdpDasColumnService.searchByTableId(tableIdList);
        if (CollectionUtils.isNotEmpty(bdpDasColumnDTOList)) {
            columnRelatedMap =
                    bdpDasColumnDTOList.stream().collect(Collectors.groupingBy(BdpColumnDTO::getTableId));
        }

        for (SimpleModelDTO modelRequest : modelList) {
            TableCompareResponseDTO tableCompareResponse = new TableCompareResponseDTO();
            List<ColumnCompareResponseDTO> comparisonResult = new ArrayList<>();
            String tableName = modelRequest.getName();
            String dataSourceId = modelRequest.getDataSourceId();
            String typeId = modelRequest.getTypeId();

            tableCompareResponse.setTableName(tableName);
            tableCompareResponse.setComparisonResult(comparisonResult);
            tableCompareResponse.setTableSame(true);
            tableCompareResponse.setResult("模型和物理表一致");
            response.add(tableCompareResponse);

            BdpTableDTO bdpDasTableDTO = typeRelatedModelMap.get(typeId + tableName);
            if (bdpDasTableDTO == null) {
                tableCompareResponse.setTableSame(false);
                tableCompareResponse.setResult("模型不存在");
                continue;
            }
            tableCompareResponse.setId(bdpDasTableDTO.getId());
            tableCompareResponse.setDataSourceName(modelRequest.getModelDataSourceName());
            tableCompareResponse.setDataSourceType(modelRequest.getDataSourceType());

            // 模型存在数据源ID，但和本次导入的数据源不一致
            // String modelDataSourceId = bdpDasTableDTO.getDataSourceId();
            // if (StringUtils.isNotBlank(modelDataSourceId) && !modelDataSourceId.equals(dataSourceId)) {
            //    tableCompareResponse.setEnable(false);
            //    tableCompareResponse.setTableSame(false);
            //    tableCompareResponse.setResult("模型已落库过，不能落库到其他数据库");
            //    continue;
            // }

            DataSourceDTO dataSourceDTO = dbCache.get(dataSourceId);
            if (dataSourceDTO == null) {
                dataSourceDTO = bdpDasDatasourceService.selectByPrimaryKey(dataSourceId);
                if (dataSourceDTO == null) {
                    tableCompareResponse.setTableSame(false);
                    tableCompareResponse.setEnable(false);
                    tableCompareResponse.setResult("数据源不存在");
                    continue;
                }
                dbCache.put(dataSourceId, dataSourceDTO);
            }

            // 处理模型结构
            try {
                handleModel(
                        tableCompareResponse,
                        comparisonResult,
                        tableName,
                        bdpDasTableDTO,
                        columnRelatedMap,
                        dataSourceDTO);
            } catch (Exception e) {
                tableCompareResponse.setTableSame(false);
                tableCompareResponse.setResult("模型比对异常，请联系管理员");
                tableCompareResponse.setEnable(false);
            }
        }

        return response;
    }

    private List<SimpleModelDTO> getSimpleModelList(
            TableCompareRequestDTO compareDto,
            List<SimpleModelDTO> modelList,
            List<String> typeIdList,
            List<String> tableIdList,
            Map<String, DataSourceDTO> dbCache,
            Map<String, BdpTableDTO> typeRelatedModelMap) {
        if (CollectionUtils.isEmpty(modelList)) {
            // 请求参数模型比对数组为空，则查询模型表下所有可导入的表（通过分类ID和数据源类型查询）
            String dataSourceId = compareDto.getDataSourceId();
            DataSourceDTO dataSourceDTO = bdpDasDatasourceService.selectByPrimaryKey(dataSourceId);
            String typeId = compareDto.getTypeId();
            if (dataSourceDTO == null) {
                throw new BusinessException("数据源不存在");
            }

            dbCache.put(dataSourceId, dataSourceDTO);

            modelList = new ArrayList<>();
            typeIdList.add(typeId);

            String dbType = dataSourceDTO.getDatasourceType();
            List<BdpTableDTO> tableList = mapper.selectTableList(null, typeIdList, 0, dbType, 0, null);
            if (CollectionUtils.isNotEmpty(tableList)) {
                DataSourceDTO modelDataSource;
                for (BdpTableDTO bdpDasTableDTO : tableList) {
                    SimpleModelDTO simpleModelDTO = new SimpleModelDTO();
                    simpleModelDTO.setDataSourceId(dataSourceId);
                    simpleModelDTO.setDataSourceType(bdpDasTableDTO.getDataSourceType());
                    simpleModelDTO.setName(bdpDasTableDTO.getName());
                    simpleModelDTO.setTypeId(typeId);
                    if (StringUtils.isNotBlank(bdpDasTableDTO.getDataSourceId())) {
                        if (dbCache.containsKey(bdpDasTableDTO.getDataSourceId())) {
                            modelDataSource = dbCache.get(bdpDasTableDTO.getDataSourceId());
                        } else {
                            modelDataSource =
                                    bdpDasDatasourceService.selectByPrimaryKey(bdpDasTableDTO.getDataSourceId());
                        }
                        if (modelDataSource != null) {
                            simpleModelDTO.setModelDataSourceName(modelDataSource.getDatasourceName());
                        }
                    }
                    modelList.add(simpleModelDTO);
                }
            }

            // 分类下相关的模型
            List<BdpTableDTO> typeRelatedModel =
                    this.mapper.selectTableList(null, typeIdList, 0, null, 0, null);
            // 模型按照分类分组
            typeRelatedModel.parallelStream()
                    .forEach(
                            model -> {
                                tableIdList.add(model.getId());
                                typeRelatedModelMap.put(model.getTypeId() + model.getName(), model);
                            });
        } else {
            modelList.forEach(
                    model -> {
                        typeIdList.add(model.getTypeId());
                        tableIdList.add(model.getTableId());
                        BdpTableDTO bdpDasTableDTO = new BdpTableDTO();
                        bdpDasTableDTO.setId(model.getTableId());
                        bdpDasTableDTO.setDataSourceId(model.getDataSourceId());
                        bdpDasTableDTO.setDataSourceType(model.getDataSourceType());
                        bdpDasTableDTO.setName(model.getName());
                        bdpDasTableDTO.setTypeId(model.getTypeId());
                        DataSourceDTO dataSourceDTO;
                        if (dbCache.containsKey(model.getDataSourceId())) {
                            dataSourceDTO = dbCache.get(model.getDataSourceId());
                        } else {
                            dataSourceDTO = bdpDasDatasourceService.selectByPrimaryKey(model.getDataSourceId());
                        }
                        if (dataSourceDTO != null) {
                            model.setModelDataSourceName(dataSourceDTO.getDatasourceName());
                        }
                        typeRelatedModelMap.put(model.getTypeId() + model.getName(), bdpDasTableDTO);
                    });
        }
        return modelList;
    }

    private void handleModel(
            TableCompareResponseDTO tableCompareResponse,
            List<ColumnCompareResponseDTO> comparisonResult,
            String tableName,
            BdpTableDTO bdpDasTableDTO,
            Map<String, List<BdpColumnDTO>> columnRelatedMap,
            DataSourceDTO dataSourceDTO) {
        // 模型表列名集合
        List<String> modelColumnNameList = new ArrayList<>();
        Map<String, BdpColumnDTO> modelColumnMap = new HashMap<>(16);
        // 数据库列名集合
        List<String> dbColumnNameList = new ArrayList<>();
        Map<String, BdpColumnDTO> dbColumnMap = new HashMap<>(16);

        tableCompareResponse.setDataSourceId(dataSourceDTO.getId());

        try {
            // 模型字段
            List<BdpColumnDTO> modelColumnList = columnRelatedMap.get(bdpDasTableDTO.getId());
            if (CollectionUtils.isNotEmpty(modelColumnList)) {
                List<BdpColumnDTO> orderedList =
                        modelColumnList.stream()
                                .sorted(Comparator.comparing(BdpColumnDTO::getOrderBy))
                                .collect(Collectors.toList());
                orderedList.forEach(
                        columnDto -> {
                            modelColumnNameList.add(columnDto.getName().toLowerCase());
                            modelColumnMap.put(columnDto.getName().toLowerCase(), columnDto);
                        });
            } else {
                tableCompareResponse.setTableSame(false);
                tableCompareResponse.setResult("模型列数据不存在");
                tableCompareResponse.setModelExist(false);
            }

            TableMeta tableMeta = DBUtils.getTable(DBUtils.getBaseDataSource(dataSourceDTO), tableName);
            if (tableMeta != null) {
                List<ColumnMeta> columnMetaList = tableMeta.getColumnMetaData();
                handleTableMetaColumn(bdpDasTableDTO, tableMeta);
                if (CollectionUtils.isNotEmpty(columnMetaList)) {
                    List<BdpColumnDTO> columnList = bdpDasTableDTO.getColumnList();
                    columnList.forEach(
                            columnDto -> {
                                dbColumnNameList.add(columnDto.getName().toLowerCase());
                                dbColumnMap.put(columnDto.getName().toLowerCase(), columnDto);
                            });
                } else {
                    tableCompareResponse.setTableSame(false);
                    tableCompareResponse.setResult("数据库表未查询到列数据");
                }

            } else {
                tableCompareResponse.setTableSame(false);
                tableCompareResponse.setResult("数据库不存在表" + tableName);
                tableCompareResponse.setDatabaseExist(false);
            }

            for (String dbColumnName : dbColumnNameList) {
                if (!modelColumnNameList.contains(dbColumnName)) {
                    modelColumnNameList.add(dbColumnName);
                }
            }

            // 处理并比对列差异
            modelColumnNameList.forEach(
                    columnName -> {
                        ColumnCompareResponseDTO columnCompare =
                                compareColumn(tableCompareResponse, modelColumnMap, dbColumnMap, columnName);

                        comparisonResult.add(columnCompare);
                    });

        } catch (Exception e) {
            logger.error("比对表结构异常", e);
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 比较模型和库表列
     *
     * @param tableCompareResponse 表对比结果
     * @param modelColumnMap       模型列数据集
     * @param dbColumnMap          库表列数据集
     * @param columnName           列名
     * @return 列对比结果
     */
    private ColumnCompareResponseDTO compareColumn(
            TableCompareResponseDTO tableCompareResponse,
            Map<String, BdpColumnDTO> modelColumnMap,
            Map<String, BdpColumnDTO> dbColumnMap,
            String columnName) {

        ColumnCompareResponseDTO columnCompareResult = new ColumnCompareResponseDTO();

        BdpColumnDTO modelColumn = modelColumnMap.get(columnName);
        BdpColumnDTO dbColumn = dbColumnMap.get(columnName);

        modelColumn = modelColumn == null ? new BdpColumnDTO() : modelColumn;
        dbColumn = dbColumn == null ? new BdpColumnDTO() : dbColumn;

        // 比较字段名
        ColumnCompareResponseDetail columnNameDetail = new ColumnCompareResponseDetail();
        handleColumnCompareResponse(
                tableCompareResponse,
                columnNameDetail,
                modelColumn.getName() == null ? null : modelColumn.getName().toLowerCase(),
                dbColumn.getName() == null ? null : dbColumn.getName().toLowerCase());
        columnCompareResult.setColumnName(columnNameDetail);

        // 比较类型
        ColumnCompareResponseDetail columnTypeDetail = new ColumnCompareResponseDetail();
        String modelColumnType =
                modelColumn.getColumnType() == null ? null : modelColumn.getColumnType().toLowerCase();
        String dbColumnType =
                dbColumn.getColumnType() == null ? null : modelColumn.getColumnType().toLowerCase();
        handleColumnCompareResponse(
                tableCompareResponse, columnTypeDetail, modelColumnType, dbColumnType);
        columnCompareResult.setColumnType(columnTypeDetail);

        // 比较长度
        ColumnCompareResponseDetail columnLengthDetail = new ColumnCompareResponseDetail();
        handleColumnCompareResponse(
                tableCompareResponse,
                columnLengthDetail,
                modelColumn.getColumnLength(),
                dbColumn.getColumnLength());
        columnCompareResult.setColumnLength(columnLengthDetail);

        // 比较精度
        ColumnCompareResponseDetail precisionDetail = new ColumnCompareResponseDetail();
        handleColumnCompareResponse(
                tableCompareResponse,
                precisionDetail,
                modelColumn.getColumnPrecision() == null ? 0 : modelColumn.getColumnPrecision(),
                dbColumn.getColumnPrecision() == null ? 0 : dbColumn.getColumnPrecision());
        columnCompareResult.setPrecision(precisionDetail);

        // 比较外键
        ColumnCompareResponseDetail primaryKeyDetail = new ColumnCompareResponseDetail();
        handleColumnCompareResponse(
                tableCompareResponse,
                primaryKeyDetail,
                modelColumn.getPrimaryKey(),
                dbColumn.getPrimaryKey() == null ? 0 : dbColumn.getPrimaryKey());
        columnCompareResult.setPrimaryKey(primaryKeyDetail);

        // 比较外键
        ColumnCompareResponseDetail foreignKeyDetail = new ColumnCompareResponseDetail();
        handleColumnCompareResponse(
                tableCompareResponse,
                foreignKeyDetail,
                modelColumn.getForeignKey(),
                dbColumn.getForeignKey() == null ? 0 : dbColumn.getForeignKey());
        columnCompareResult.setForeignKey(foreignKeyDetail);

        // 比较唯一
        ColumnCompareResponseDetail uniqueKeyDetail = new ColumnCompareResponseDetail();
        handleColumnCompareResponse(
                tableCompareResponse,
                uniqueKeyDetail,
                modelColumn.getUniqueKey(),
                dbColumn.getUniqueKey() == null ? 0 : dbColumn.getUniqueKey());
        columnCompareResult.setUnique(uniqueKeyDetail);

        // 比较是否为空
        ColumnCompareResponseDetail nullableDetail = new ColumnCompareResponseDetail();
        handleColumnCompareResponse(
                tableCompareResponse,
                nullableDetail,
                modelColumn.getNullable(),
                dbColumn.getNullable() == null ? 0 : dbColumn.getNullable());
        columnCompareResult.setNullable(nullableDetail);

        // 比较备注
        // ColumnCompareResponseDetail remarkDetail = new ColumnCompareResponseDetail();
        // handleColumnCompareResponse(tableCompareResponse, remarkDetail,
        //        modelColumn.getRemark(), dbColumn.getRemark());
        // columnCompareResult.setRemark(remarkDetail);

        return columnCompareResult;
    }

    private void handleColumnCompareResponse(
            TableCompareResponseDTO tableCompareResponse,
            ColumnCompareResponseDetail columnCompareResponseDetail,
            Object modelValue,
            Object dbValue) {

        columnCompareResponseDetail.setModel(tableCompareResponse.isModelExist() ? modelValue : null);
        columnCompareResponseDetail.setDatabase(
                tableCompareResponse.isDatabaseExist() ? dbValue : null);
        boolean isSame = Objects.equals(modelValue, dbValue);
        columnCompareResponseDetail.setSame(isSame);
        if (!isSame && tableCompareResponse.isModelExist() && tableCompareResponse.isDatabaseExist()) {
            tableCompareResponse.setTableSame(false);
            tableCompareResponse.setResult("模型和物理表结构不一致");
        }
    }

    /**
     * 数据源模型导入
     *
     * @param dataSourceId 数据源ID
     * @param tables       表ID集合
     * @param typeId       分类ID
     * @param type         模型类型
     */
    public Map<String, List<String>> importModel(
            String dataSourceId, String tables, String typeId, int type) {
        DataSourceDTO dataSourceDTO = bdpDasDatasourceService.queryDataSourceById(dataSourceId);
        if (dataSourceDTO == null) {
            throw new BusinessException("数据源不存在");
        }

        Map<String, List<String>> result = new HashMap<>(2);
        List<String> successList = new LinkedList<>();
        List<String> errorList = new LinkedList<>();
        result.put("successList", successList);
        result.put("errorList", errorList);

        String[] tableArr = tables.split(Constants.COMMA);

        if (tableArr.length > 0) {
            int modelX = 100;
            int modelY = 50 + mapper.selectMaxYByTypeId(typeId);
            int i = 0;
            int maxSize = 0;
            for (String tableName : tableArr) {
                try {
                    // 获取列信息
                    TableMeta tableMeta =
                            DBUtils.getTable(DBUtils.getBaseDataSource(dataSourceDTO), tableName);
                    if (tableMeta != null && CollectionUtils.isNotEmpty(tableMeta.getColumnMetaData())) {
                        BdpTableDTO dasTableDTO = new BdpTableDTO();
                        dasTableDTO.setId(ComUtil.getId());
                        dasTableDTO.setName(tableName);
                        dasTableDTO.setSecretLevel(dataSourceDTO.getSecretLevel());
                        if (StringUtils.isNotBlank(tableMeta.getCnName())) {
                            dasTableDTO.setCnName(tableMeta.getCnName());
                        } else if (StringUtils.isNotBlank(tableMeta.getRemark())) {
                            String remark = tableMeta.getRemark();
                            if (tableMeta.getRemark().length() > 200) {//备注大于200，只截取200字符
                                remark = tableMeta.getRemark().substring(0, 200);
                            }
                            dasTableDTO.setCnName(remark);
                        } else {
                            dasTableDTO.setCnName(tableName);
                        }
                        if (StringUtils.isNotBlank(tableMeta.getRemark())) {
                            dasTableDTO.setRemark(tableMeta.getRemark());
                        }
                        dasTableDTO.setTypeId(typeId);
                        dasTableDTO.setType(type);
                        dasTableDTO.setDataSourceId(dataSourceId);
                        dasTableDTO.setDataSourceType(dataSourceDTO.getDatasourceType());
                        dasTableDTO.setStoreStatus(ModelStoreStatusEnum.STORE_STATUS_SAVED.ordinal());
                        dasTableDTO.setSkipAddToDb(true);
                        dasTableDTO.setDataStorageFormat(tableMeta.getDataStorageFormat());
                        dasTableDTO.setTableVersion("1.0");
                        dasTableDTO.setSourceType(3);
                        // 数据建模,处理默认位置和大小
                        if (type == 4) {
                            i++;
                            int size = tableMeta.getColumnMetaData().size();
                            int maxLengthByTableMeta = getMaxLengthByTableMeta(tableMeta);
                            maxSize = Math.max(size, maxSize);
                            dasTableDTO.setModelX(modelX);
                            dasTableDTO.setModelY(modelY);
                            dasTableDTO.setModelHeight(28 * (size + 1));
                            dasTableDTO.setModelWidth(maxLengthByTableMeta * 6 + 50);
                            modelX += dasTableDTO.getModelWidth() + 50;
                            if (i % 5 == 0) {
                                modelX = 100;
                                modelY += (maxSize + 2) * 28;
                                maxSize = 0;
                            }
                        }
                        handleTableMetaColumn(dasTableDTO, tableMeta);
                        dasTableDTO.setStorageGroup(tableMeta.getStorageGroup());

                        Map<String, Object> insertResult = insertDataTable(dasTableDTO);

                        if (insertResult != null && insertResult.containsKey("tableId")) {
                            successList.add(tableName);
                        } else {
                            handErrorMsg(errorList, tableName, "导入失败,请联系管理员");
                        }
                    } else {
                        logger.error("数据源[{}]导入模型[{}]，没有获取到表信息", dataSourceId, tableName);
                        handErrorMsg(errorList, tableName, "没有获取到表信息");
                    }

                } catch (Exception e) {
                    handErrorMsg(errorList, tableName, "导入失败,请联系管理员");
                    logger.error("数据源[{}]导入模型[{}]，异常{}", dataSourceId, tableName, e);
                }
            }
        }

        // 记录日志
        String tableNames = StringUtils.join(successList,",");
        String logTitle = "数据库导入：数据源【" + dataSourceDTO.getDatasourceName() + "】，模型：【" +tableNames+"】";
        BdpLogUtil.log("物理模型模块", logTitle, PlatformConstant.OpType.update);
        return result;
    }

    private int getMaxLengthByTableMeta(TableMeta tableMeta) {
        int maxLength = tableMeta.getName().length();
        List<ColumnMeta> columnMetaData = tableMeta.getColumnMetaData();
        for (ColumnMeta columnMetaDatum : columnMetaData) {
            maxLength =
                    Math.max(
                            maxLength,
                            (columnMetaDatum.getColumnType()
                                    + columnMetaDatum.getName()
                                    + columnMetaDatum.getColumnLength())
                                    .length()
                                    + 4);
        }
        return maxLength;
    }

    private void handleTableMetaColumn(BdpTableDTO dasTableDTO, TableMeta tableMeta) {
        List<ColumnMeta> columnMetaList = tableMeta.getColumnMetaData();
        if (Constants.DB_TYPE_IOTDB.equals(dasTableDTO.getDataSourceType())) {
            ColumnMeta columnMeta = new ColumnMeta();
            columnMeta.setName("Time");
            columnMeta.setCnName("Time");
            columnMeta.setColumnType("timestamp");
            columnMeta.setNullable(1);
            columnMetaList.add(0, columnMeta);
        }
        List<BdpColumnDTO> columnList = new ArrayList<>();
        List<ColumnPartitionedDTO> columnPartitioneds = new ArrayList<>();
        int order = 1;
        for (ColumnMeta columnMeta : columnMetaList) {
            if (Constants.DB_TYPE_HIVE.equals(dasTableDTO.getDataSourceType())
                    && columnMeta.getPartitionable() != null
                    && 1 == columnMeta.getPartitionable()) {
                columnPartitioneds.add(createPartitionColumnByMetaData(dasTableDTO, columnMeta, order++));
            } else {
                columnList.add(createColumnByMetaData(dasTableDTO, columnMeta, order++));
            }
        }
        dasTableDTO.setPartitionedColumnList(columnPartitioneds);
        dasTableDTO.setColumnList(columnList);
    }

    private ColumnPartitionedDTO createPartitionColumnByMetaData(
            BdpTableDTO dasTableDTO, ColumnMeta columnMeta, int order) {
        ColumnPartitionedDTO partitionedDTO = new ColumnPartitionedDTO();
        partitionedDTO.setId(ComUtil.getId());
        if (dasTableDTO != null) {
            partitionedDTO.setTableId(dasTableDTO.getId());
        }
        partitionedDTO.setName(columnMeta.getName());
        partitionedDTO.setRemark(columnMeta.getRemark());
        partitionedDTO.setColumnType(columnMeta.getColumnType());
        partitionedDTO.setOrderBy(order);

        EntityUtils.setCreateAndUpdateInfo(partitionedDTO);
        return partitionedDTO;
    }

    /**
     * 模型同步
     *
     * @param modelList 同步模型列表
     * @return 同步结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, List<String>> syncModel(List<BdpTableDTO> modelList) {

        Map<String, List<String>> result = new HashMap<>(2);
        List<String> successList = new LinkedList<>();
        List<String> errorList = new LinkedList<>();
        List<String> successTableList = new LinkedList<>();
        result.put("successList", successList);
        result.put("errorList", errorList);

        Map<String, DataSourceDTO> dbCacheMap = new ConcurrentHashMap<>(16);
        List<String> tableIdList = new CopyOnWriteArrayList<>();
        List<BdpColumnDTO> allColumnList = new CopyOnWriteArrayList<>();

        if (CollectionUtils.isNotEmpty(modelList)) {
            for (BdpTableDTO bdpDasTableDTO : modelList) {
                BdpTableDTO table = selectByPrimaryKey(bdpDasTableDTO.getId());
                bdpDasTableDTO.setDataSourceType(table.getDataSourceType());
            }
        }
        Map<String, String> oldColumnMap = new ConcurrentHashMap<>(16);
        modelList.parallelStream().forEach(model -> tableIdList.add(model.getId()));
        List<BdpColumnDTO> oldColumnList = bdpDasColumnService.searchByTableId(tableIdList);
        if (CollectionUtils.isNotEmpty(oldColumnList)) {
            for (BdpColumnDTO columnDTO : oldColumnList) {
                oldColumnMap.put(
                        columnDTO.getTableId() + columnDTO.getName().toLowerCase(), columnDTO.getId());
            }
        }

        modelList.parallelStream()
                .forEach(
                        model -> {
                            String tableId = model.getId();
                            String tableName = model.getName();
                            String dataSourceId = model.getDataSourceId();
                            DataSourceDTO dataSourceDTO = dbCacheMap.get(dataSourceId);

                            try {
                                if (dataSourceDTO == null) {
                                    dataSourceDTO = bdpDasDatasourceService.queryDataSourceById(dataSourceId);
                                    if (dataSourceDTO == null) {
                                        handErrorMsg(errorList, tableName, "未找到数据源");
                                        return;
                                    } else {
                                        dbCacheMap.put(dataSourceId, dataSourceDTO);
                                    }
                                }

                                // 获取列信息
                                TableMeta tableMeta =
                                        DBUtils.getTable(DBUtils.getBaseDataSource(dataSourceDTO), tableName);
                                // 存在表
                                if (tableMeta != null) {
                                    handleTableMetaColumn(model, tableMeta);

                                    String remark = tableMeta.getRemark();
                                    if (StringUtils.isNotBlank(tableMeta.getDataStorageFormat())) {
                                        model.setDataStorageFormat(tableMeta.getDataStorageFormat());
                                    }
                                    model.setRemark(remark);
                                    if (StringUtils.isNotBlank(tableMeta.getCnName())) {
                                        model.setCnName(tableMeta.getCnName());
                                    }
                                    // 如果是编辑中的状态，则改为已落库
                                    model.setStoreStatus(ModelStoreStatusEnum.STORE_STATUS_SAVED.ordinal());
                                    updateByPrimaryKeySelective(model);

                                    // 添加新的字段列表
                                    List<BdpColumnDTO> columnList = model.getColumnList();

                                    for (BdpColumnDTO bdpDasColumnDTO : columnList) {
                                        // 给字段赋值表ID,如果字段名称存在过，则保留初始ID
                                        bdpDasColumnDTO.setTableId(tableId);
                                        String name = tableId + bdpDasColumnDTO.getName().toLowerCase();
                                        String id;
                                        if (oldColumnMap.containsKey(name)) {
                                            id = oldColumnMap.get(name);
                                        } else {
                                            id = ComUtil.getId();
                                        }
                                        bdpDasColumnDTO.setId(id);
                                        EntityUtils.setCreateAndUpdateInfo(bdpDasColumnDTO);
                                        allColumnList.add(bdpDasColumnDTO);
                                    }

                                    successList.add(tableName);
                                    successTableList.add(tableId);
                                } else {
                                    logger.error("同步模型[{}]失败，没有获取到表信息", tableName);
                                    handErrorMsg(errorList, tableName, "数据库不存在表" + tableName);
                                }

                            } catch (Exception e) {
                                logger.error("同步模型[{}]失败", tableName, e);
                                handErrorMsg(errorList, tableName, e.getMessage());
                            }
                        });

        // 批量删除列和添加列
        batchHandleColumn(successTableList, allColumnList);

        // 记录日志
        String tableNames = StringUtils.join(successList, ",");
        String logTitle = "模型同步：模型：【" + tableNames + "】";
        BdpLogUtil.log("数据模型模块", logTitle, PlatformConstant.OpType.update);

        return result;
    }

    private void handErrorMsg(List<String> errorList, String tableName, String msg) {
        Map<String, String> errorMap = new HashMap<>(4);
        errorMap.put("name", tableName);
        errorMap.put("errorMsg", msg);
        errorList.add(JSONUtils.toJsonString(errorMap));
    }

    /**
     * 批量删除列和添加列
     *
     * @param tableIdList   表ID列表
     * @param allColumnList 待插入列数据
     */
    private void batchHandleColumn(List<String> tableIdList, List<BdpColumnDTO> allColumnList) {
        // 批量删出列
        if (CollectionUtils.isNotEmpty(tableIdList)) {
            bdpDasColumnService.deleteByTableIdList(tableIdList);
        }

        // 批量添加列
        if (CollectionUtils.isNotEmpty(allColumnList)) {
            int start = 0;
            int totalSize = allColumnList.size();
            while (true) {
                // 以1000条记录为单位分批存储
                int end = Math.min(start + 1000, totalSize);
                bdpDasColumnService.insertListByBatch(allColumnList.subList(start, end));
                if (end >= totalSize) {
                    break;
                }
                start = end;
            }
        }
    }

    /**
     * 查询表列表，并查询表的导入状态
     *
     * @param dataSourceId 数据源ID
     * @param typeIdList   分类ID集合
     * @param keyword      关键词
     * @return 模型导入状态列表
     * @throws Exception e
     */
    public List<BdpTableDTO> getTableListAndStatusByDatasourceId(
            String dataSourceId, List<String> typeIdList, String keyword) throws Exception {
        LinkedList<BdpTableDTO> result = new LinkedList<>();

        // 查询数据库表列表
        List<TableMeta> tableMetaList =
                dataSourceService.getTableListByDatasourceId(dataSourceId, false);
        // 查询该分类下导入的表
        if (CollectionUtils.isNotEmpty(tableMetaList)) {
            Map<String, BdpTableDTO> nameMap = new ConcurrentHashMap<>(16);
            Map<String, BdpTableDTO> dbMap = new ConcurrentHashMap<>(16);

            // 当前分类下名称不能重复,查询当前分类下所有的物理模型
            List<BdpTableDTO> typeTableList = selectTableList(null, typeIdList, 5, null, null);
            if (CollectionUtils.isNotEmpty(typeTableList)) {
                typeTableList.parallelStream()
                        .forEach(
                                bdpDasTableDTO ->
                                        nameMap.put(bdpDasTableDTO.getName().toLowerCase(), bdpDasTableDTO));
            }

            // 当前表在所有分类下只能导入一次,查看当前数据源在所有分类里面导入的模型 [dataSourceId + name]
            List<BdpTableDTO> dbTableList = selectTableList(null, null, 5, null, dataSourceId);
            if (CollectionUtils.isNotEmpty(dbTableList)) {
                dbTableList.parallelStream()
                        .forEach(
                                bdpDasTableDTO ->
                                        dbMap.put(
                                                dataSourceId + bdpDasTableDTO.getName().toLowerCase(), bdpDasTableDTO));
            }

            for (TableMeta tableMeta : tableMetaList) {
                String name = tableMeta.getName();
                if (StringUtils.isNotBlank(keyword)
                        && !name.toLowerCase().contains(keyword.toLowerCase())) {
                    continue;
                }
                if (nameMap.containsKey(name.toLowerCase())
                        || dbMap.containsKey(dataSourceId + name.toLowerCase())) {
                    BdpTableDTO dasTableDTO = nameMap.get(name.toLowerCase());
                    if (dasTableDTO == null) {
                        dasTableDTO = dbMap.get(dataSourceId + name.toLowerCase());
                        dasTableDTO.setTableStatus("当前表已在其他分类下导入");
                    } else {
                        dasTableDTO.setTableStatus("不能导入，当前分类已存在同名表");
                    }
                    dasTableDTO.setImported(1);
                    result.addLast(dasTableDTO);
                } else {
                    BdpTableDTO dto = new BdpTableDTO();
                    dto.setName(tableMeta.getName());
                    dto.setCnName(tableMeta.getName());
                    dto.setTableStatus("未导入");
                    result.addFirst(dto);
                }
            }
        }

        return result;
    }

    private BdpColumnDTO createColumnByMetaData(
            BdpTableDTO dasTableDTO, ColumnMeta columnMeta, int order) {
        BdpColumnDTO column = new BdpColumnDTO();
        column.setId(ComUtil.getId());
        if (dasTableDTO != null) {
            column.setTableId(dasTableDTO.getId());
        }
        column.setName(columnMeta.getName());
        column.setCnName(columnMeta.getCnName());
        column.setRemark(columnMeta.getRemark());
        column.setColumnLength(columnMeta.getColumnLength());
        column.setColumnPrecision(columnMeta.getColumnPrecision());
        column.setColumnType(columnMeta.getColumnType());
        column.setOrderBy(order);
        // 不可修改
        column.setModifyable(0);
        column.setNullable(columnMeta.getNullable() == null ? 0 : columnMeta.getNullable());
        column.setPrimaryKey(columnMeta.getPrimaryKey() == null ? 0 : columnMeta.getPrimaryKey());
        column.setForeignKey(columnMeta.getForeignKey() == null ? 0 : columnMeta.getForeignKey());
        column.setUniqueKey(columnMeta.getUniqueKey() == null ? 0 : columnMeta.getPrimaryKey());
        EntityUtils.setCreateAndUpdateInfo(column);
        return column;
    }

    /**
     * 判断物理数据表中是否有数据
     *
     * @param tableId 模型ID
     * @return java.lang.Integer
     * @author felix
     * @date 2020/12/4 10:20
     */
    @Transactional
    public Integer tableData(String tableId) {
        if (StringUtils.isBlank(tableId)) {
            throw new BusinessException("参数为空");
        }
        Integer flag = 0;
        BdpTableDTO tableDTO = selectByPrimaryKey(tableId);
        if (tableDTO == null) {
            throw new BusinessException("对象不存在!");
        }
        if (tableDTO.getStoreStatus() != 0) {
            DataSourceDTO datasource = dataSourceService.selectByPrimaryKey(tableDTO.getDataSourceId());
            DbAdapter adapter = DbAdapterUtils.getDbAdapter(datasource.getDatasourceType());
            BaseDataSource dbsource = DBUtils.getBaseDataSource(datasource);
            StringBuilder sql = new StringBuilder();
            sql.append("select * from ").append(tableDTO.getName());
            if (Constants.DB_TYPE_ORACLE.equals(datasource.getDatasourceType().toLowerCase())) {
                sql.append(" where ROWNUM = 1");
            } else if (Constants.DB_TYPE_IOTDB.equals(datasource.getDatasourceType().toLowerCase())) {

            } else {
                sql.append(" limit 1");
            }
            Map<String, Object> result;

            try {
                result = adapter.getTableDataListFromDb(dbsource, sql.toString(), null, 5, null);
                List resultList = (List) result.get("resultList");
                if (resultList != null && resultList.size() > 0) {
                    flag = 1;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return flag;
    }

    @Transactional(readOnly = true)
    public List<BdpTableDTO> getTableList(String typeId, String projectId) {
        try {
            List<String> typeIds =
                    commonTypeService.getChildrenIds(CommonTypeEnums.DATATABLE, typeId, projectId);
            if (typeIds == null) {
                typeIds = newArrayList();
            }
            typeIds.add(typeId);

            List<BdpTableDTO> tableList = this.mapper.getTableList(typeIds, projectId);
            return tableList;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 对外接口，根据tableId查询模型表信息
     *
     * @param tableId
     * @return
     */
    @Transactional(readOnly = true)
    public BdpTableDTO queryTableInfoById(String tableId) {
        CheckParaUtils.checkStringValidity(tableId, logger, "模型表ID为null.");

        BdpTableDTO bdpTableDTO = selectByPrimaryKey(tableId);
        CheckParaUtils.checkObjectValidity(bdpTableDTO, logger, "查询模型表" + tableId + "失败.");

        return bdpTableDTO;
    }

    /**
     * 对外接口，根据tableId，获取模型表字段信息;
     *
     * @param tableId
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpColumnDTO> queryColumnInfoById(String tableId) {
        if (StringUtils.isEmpty(tableId)) {
            throw new BusinessException("模型表ID为null.");
        }

        BdpColumnDTO query = new BdpColumnDTO();
        query.setTableId(tableId);
        List<BdpColumnDTO> bdpColumnDTOS = bdpDasColumnService.selectList(query);
        if (bdpColumnDTOS == null || bdpColumnDTOS.size() <= 0) {
            throw new BusinessException(
                    avicit.platform6.commons.utils.StringUtils.format("没有获取到模型表{}得列信息.", tableId));
        }

        return bdpColumnDTOS;
    }

    private Map<String, Object> convertMsgMap(BdpTableDTO dto) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", dto.getId());
        map.put("name", dto.getName());
        map.put("cn_name", dto.getCnName());
        map.put("type_id", dto.getTypeId());
        map.put("type", dto.getType());
        map.put("datasource_id", dto.getDataSourceId());
        map.put("store_status", 1);
        map.put("datasource_type", dto.getDataSourceType());
        map.put("storage_groupe", dto.getStorageGroup());
        map.put("data_storage_format", dto.getDataStorageFormat());
        map.put("remark", dto.getRemark());
        map.put("created_by", dto.getCreatedBy());
        map.put("creation_date", DateUtils.format(dto.getCreationDate()));
        map.put("last_updated_by", dto.getLastUpdatedBy());
        map.put("last_update_date", DateUtils.format(dto.getLastUpdateDate()));
        List<BdpColumnDTO> columnList = dto.getColumnList();
        List<Map<String, Object>> list = new ArrayList<>();
        if (columnList != null) {
            for (BdpColumnDTO column : columnList) {
                Map<String, Object> cmap = new HashMap<>();
                cmap.put("id", column.getId());
                cmap.put("name", column.getName());
                cmap.put("cn_name", column.getCnName());
                cmap.put("column_type", column.getColumnType());
                cmap.put("column_length", column.getColumnLength());
                cmap.put("column_precision", column.getColumnPrecision());
                cmap.put("nullable", column.getNullable());
                cmap.put("primaryKey", column.getPrimaryKey());
                cmap.put("uniqueKey", column.getUniqueKey());
                cmap.put("modifyable", column.getModifyable());
                cmap.put("table_id", column.getTableId());
                cmap.put("remark", column.getRemark());
                cmap.put("order_by", column.getOrderBy());
                cmap.put("created_by", column.getCreatedBy());
                cmap.put("creation_date", DateUtils.format(column.getCreationDate()));
                cmap.put("last_updated_by", column.getLastUpdatedBy());
                cmap.put("last_update_date", DateUtils.format(column.getLastUpdateDate()));
                list.add(cmap);
            }
        }
        map.put("columnList", list);

        return map;
    }

    /**
     * @导入逻辑模型excel
     * @参数
     * @返回值
     */
    public String importLogicModelExcel(Integer cover,
                                        String convertParams, String typeId, MultipartFile file) {
        // 返回信息
        String resultInfo = "";
        Map<String, String> typeMap = new HashMap<>();
        if (StringUtils.isNotBlank(convertParams)) {
            try {
                convertParams = convertParams.replaceAll("；", ";");
                convertParams = convertParams.replaceAll("：", ":");
                String[] params = convertParams.split(";");
                for (String param : params) {
                    String[] keyValues = param.split(":");
                    typeMap.put(keyValues[0].trim(), keyValues[1].trim());
                }
            } catch (Exception e) {
                return "转换信息识别错误，请检查！";
            }
        }
        // 导入表的总条数
        int totalCount = 0;
        // 失败条数
        int failCount = 0;
        // 失败表集合
        List<ModelExcelDTO> errorTableList = new ArrayList<>();
        try {
            // file从前端传过来的 直接接收  或者自己读取一个InputStream
            Workbook wb = new XSSFWorkbook(file.getInputStream());
            int sheetNum = wb.getNumberOfSheets();
            //判断需要解析的sheet页
            int index = 0;
            for (int i = 0; i < sheetNum; i++) {
                Sheet sheet1 = wb.getSheetAt(i);
                for (int j = 0; j <= 100; j++) {
                    Row r = sheet1.getRow(j);
                    Row n = sheet1.getRow(j + 1);
                    if (r != null && n != null &&
                            "模型名称".equals(PoiCellUtil.getCellValue(r.getCell(0))) &&
                            "定义与范围".equals(PoiCellUtil.getCellValue(n.getCell(0)))) {
                        index = i;
                        break;
                    }
                }
            }
            // 获取第0个sheet  下标从0开始
            Sheet sheet1 = wb.getSheetAt(index);

            //字段数
            int columnSize = 0;


            Map<String, Map<String, Object>> locationMap = new HashMap<>(); // 存放表位置信息

            String tableName = "";//表名
            String tableId = "";//表id
            String tableRemark = "";//表备注
            List<BdpColumnDTO> allColumnList = new ArrayList<>();//字段集合
            for (int i = 0; i <= sheet1.getLastRowNum(); i++) {
                try {
                    if (thisRowNone(sheet1.getRow(i))) {
                        continue;
                    }
                    Row row = sheet1.getRow(i);
                    if ("模型名称".equals(PoiCellUtil.getCellValue(row.getCell(0)))) {
                        tableName = PoiCellUtil.getCellValue(row.getCell(2));
                        totalCount++;
                        if (cover == 1) {
                            BdpTableDTO tableQuery = new BdpTableDTO();
                            tableQuery.setName(tableName);
                            tableQuery.setTypeId(typeId);
                            List<BdpTableDTO> bdpTableList = bdpDasTableService.selectList(tableQuery);
                            if (CollectionUtils.isNotEmpty(bdpTableList)) {
                                tableId = bdpTableList.get(0).getId();
                            } else {
                                tableId = ComUtil.getId();
                            }
                        } else {
                            tableId = ComUtil.getId();
                        }
                        continue;
                    }
                    if ("定义与范围".equals(PoiCellUtil.getCellValue(row.getCell(0)))) {
                        tableRemark = PoiCellUtil.getCellValue(row.getCell(2));
                        i++;
                        continue;
                    }
                    if ("序号".equals(PoiCellUtil.getCellValue(row.getCell(0)))) {
                        continue;
                    }
                    //字段信息
                    columnSize++;
                    handleColumn(row, tableId, allColumnList, typeMap, columnSize);

                    //先判断下一行，看字段是否结束
                    Row nextRow = sheet1.getRow(i + 1);
                    if (nextRowNone(nextRow)) {
                        BdpTableDTO bdpTableDTO = addLogictableExcel(cover, tableId, tableName, tableRemark, typeId, locationMap);
                        Integer modelHeight = columnSize * 30 + 45;
                        bdpTableDTO.setModelHeight(modelHeight);
                        bdpTableDTO.setModelWidth(modelWidth); // 宽度固定为240
                        bdpTableDTO.setSecretLevel(bdpCommonService.getMinSecretLevel());

                        // 检查列名
                        validColumnName(allColumnList);
                        List<String> tableIdList = new ArrayList<>();
                        tableIdList.add(bdpTableDTO.getId());
                        // 批量新增
                        batchHandleColumn(tableIdList, allColumnList);
                        // 都成功后再添加表
                        this.insert(bdpTableDTO);
                        //字段排序归为0
                        columnSize = 0;
                        allColumnList = new ArrayList<>();
                        continue;
                    }
                } catch (Exception e) {
                    // 存放失败对象
                    ModelExcelDTO modelExcelDTO = new ModelExcelDTO();
                    modelExcelDTO.setName(tableName);
                    modelExcelDTO.setFailInfo(e.getMessage());
                    errorTableList.add(modelExcelDTO);
                    failCount++;
                    System.out.println(e.getMessage());
                    //判断i到下一个表  此表报错走完
                    valueNextRow(sheet1, i);
                    //字段排序归为0
                    columnSize = 0;
                    continue;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String filePath = createErrorFile(errorTableList);
        // 成功条数
        int successCount = (totalCount - failCount) < 0 ? 0 : (totalCount - failCount);
        if (failCount == 0) {
            resultInfo = "成功导入" + successCount + "个表";
        } else {
            resultInfo = "成功导入" + successCount + "个表,失败" + failCount + "个表。请在导入结果中查看失败信息。";
        }
        // 记录日志
        insertSysLog(filePath, totalCount, successCount, failCount);

        String logTitle = "导入逻辑模型：【" + resultInfo + "】";
        BdpLogUtil.log("逻辑模型模块", logTitle, PlatformConstant.OpType.select);
        return resultInfo;
    }

    private void valueNextRow(
            Sheet sheet1,
            int i) {
        for (int j = i; j <= sheet1.getLastRowNum(); j++) {
            Row row = sheet1.getRow(j + 1);
            if (row == null) {
                continue;
            }
            if ("模型名称".equals(PoiCellUtil.getCellValue(row.getCell(0)))) {
                i = j;
                break;
            } else {
                continue;
            }
        }
    }

    private BdpTableDTO addLogictableExcel(
            Integer cover,
            String tableId,
            String name,
            String remark,
            String typeId,
            Map<String, Map<String, Object>> locationMap) {
        // 2 判断表是否存在
        BdpTableDTO bdpTableDTO = bdpDasTableService.selectByPrimaryKey(tableId);

        // 3 如果存在 覆盖删除并新增（id不变）
        BdpTableDTO insert = new BdpTableDTO();
        insert.setId(tableId); //tableId 前面已生成好  覆盖不变  不覆盖等同于新增
        insert.setName(name);
        insert.setCnName(remark);
        insert.setRemark(name);
        insert.setTypeId(typeId);
        insert.setType(TableTypeEnum.TABLE_LOGIC.getCode());
        insert.setStatus(DataStateEnum.UNDER_EDITING.getCode());
        if (bdpTableDTO != null) {
            bdpDasLinkService.deleteLinkByTableId(tableId);
            bdpDasTableService.deleteByPrimaryKey(tableId);
        }
        insert.setTableVersion("1.0");
        modelSite(locationMap, typeId, insert);
        return insert;
    }

    private boolean nextRowNone(Row nextRow) {
        //如果下一行为null  则表示此表已结束
        if (nextRow == null) {
            return true;
        }
        //如果下一行为新的模型名称  则表示此表已结束
        if ("模型名称".equals(PoiCellUtil.getCellValue(nextRow.getCell(0)))) {
            return true;
        }
        //如果下一行全是空值  则表示此表已结束
        if (StringUtils.isAllBlank(PoiCellUtil.getCellValue(nextRow.getCell(1)),
                PoiCellUtil.getCellValue(nextRow.getCell(2)),
                PoiCellUtil.getCellValue(nextRow.getCell(3)),
                PoiCellUtil.getCellValue(nextRow.getCell(4)),
                PoiCellUtil.getCellValue(nextRow.getCell(5)),
                PoiCellUtil.getCellValue(nextRow.getCell(6)),
                PoiCellUtil.getCellValue(nextRow.getCell(7)))) {
            return true;
        }
        return false;
    }

    private boolean thisRowNone(Row thisRow) {
        if (thisRow == null) {
            return true;
        }
        if (StringUtils.isAllBlank(PoiCellUtil.getCellValue(thisRow.getCell(1)),
                PoiCellUtil.getCellValue(thisRow.getCell(2)),
                PoiCellUtil.getCellValue(thisRow.getCell(3)),
                PoiCellUtil.getCellValue(thisRow.getCell(4)),
                PoiCellUtil.getCellValue(thisRow.getCell(5)),
                PoiCellUtil.getCellValue(thisRow.getCell(6)),
                PoiCellUtil.getCellValue(thisRow.getCell(7)))) {
            return true;
        }
        return false;
    }

    private void handleColumn(Row row, String tableId, List<BdpColumnDTO> allColumnList, Map<String, String> typeMap, int columnSize) {
        int primaryKey = ((PoiCellUtil.getCellValue(row.getCell(1)).trim()).equals("唯一性")) ? 1 : 0;
        String cnName = PoiCellUtil.getCellValue(row.getCell(2)).trim();
        String columnName = PoiCellUtil.getCellValue(row.getCell(3)).trim();
        String columnType = PoiCellUtil.getCellValue(row.getCell(4)).trim();
        String columnLength = PoiCellUtil.getCellValue(row.getCell(5)).trim();
        String columnPrecision = PoiCellUtil.getCellValue(row.getCell(6)).trim();
        int nullable = ((PoiCellUtil.getCellValue(row.getCell(7)).trim()).equals("是")) ? 0 : 1;

        //类型转换

        BdpColumnDTO bdpColumnDTO = new BdpColumnDTO();
        bdpColumnDTO.setId(ComUtil.getId());
        bdpColumnDTO.setTableId(tableId);
        bdpColumnDTO.setName(columnName);
        bdpColumnDTO.setCnName(cnName);
        bdpColumnDTO.setColumnType(LogicExcelChangValue.changeType(columnType, columnLength, columnPrecision, typeMap));
        bdpColumnDTO.setColumnLength(LogicExcelChangValue.changeLength(columnLength));
        bdpColumnDTO.setColumnPrecision(LogicExcelChangValue.changePrecision(columnPrecision));
        bdpColumnDTO.setNullable(nullable);
        bdpColumnDTO.setPrimaryKey(primaryKey);
        bdpColumnDTO.setForeignKey(0);
        bdpColumnDTO.setUniqueKey(0);
        bdpColumnDTO.setRemark(cnName);
        bdpColumnDTO.setOrderBy(columnSize);
        EntityUtils.setCreateAndUpdateInfo(bdpColumnDTO);
        allColumnList.add(bdpColumnDTO);
    }


    /**
     * 导出excel
     */
    public void exportModelExcel(String typeId, List<String> idList, HttpServletResponse response) {
        try {
            // step1:根据typeId，获取所有子节点Id
            List<String> roleIdList = this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
            List<String> typeIdList = new ArrayList<>();
            Map<String, Integer> childNodePermMap =
                    this.bdpDasCategoryService.getChildNodeMapWithPerm(typeId, roleIdList);
            if (childNodePermMap != null && childNodePermMap.size() > 0) {
                typeIdList = childNodePermMap.keySet().stream().collect(Collectors.toList());
            }
            List<BdpTableDTO> tableList = this.mapper.selectExportList(typeIdList, idList);
            List<String> tableIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(tableList)) {
                for (BdpTableDTO bdpTableDTO : tableList) {
                    tableIds.add(bdpTableDTO.getId());
                }
            }
            Map<String, List<BdpColumnDTO>> columnMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(tableIds)) {
                List<BdpColumnDTO> columnList = bdpDasColumnService.selectIdByTableIds(tableIds);
                if (CollectionUtils.isNotEmpty(columnList)) {
                    for (BdpColumnDTO bdpColumnDTO : columnList) {
                        if (columnMap.containsKey(bdpColumnDTO.getTableId())) {
                            List<BdpColumnDTO> columns = columnMap.get(bdpColumnDTO.getTableId());
                            columns.add(bdpColumnDTO);
                        } else {
                            List<BdpColumnDTO> columns = new ArrayList<>();
                            columns.add(bdpColumnDTO);
                            columnMap.put(bdpColumnDTO.getTableId(), columns);
                        }
                    }
                }
            }
            //数据组装完成，开始创建excel
            ExcelUtils excelUtils = new ExcelUtils();

            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("数据模型");
            //sheet.setColumnWidth(0, 10 * 256);//设置宽度
            //设置样式(字体居中，背景为蓝色，字体为白色  适用于标题)
            CellStyle cellStyle = setDefaultStyle(workbook);
            Font font = workbook.createFont();
            font.setColor(IndexedColors.WHITE1.getIndex());
            font.setBold(true);
            font.setFontName("宋体");
            cellStyle.setFont(font);

            // 自定义背景色
            cellStyle.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

            cellStyle.setBorderBottom(BorderStyle.THIN);
            cellStyle.setBorderTop(BorderStyle.THIN);
            cellStyle.setBorderLeft(BorderStyle.THIN);
            cellStyle.setBorderRight(BorderStyle.THIN);

            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setWrapText(true);

            //设置样式  适用于居左的值
            CellStyle cellStyle2 = setDefaultStyle(workbook);
            cellStyle2.setAlignment(HorizontalAlignment.LEFT);//设置垂直居左

            //设置样式  适用于居中的值
            CellStyle cellStyle4 = setDefaultStyle(workbook);
            cellStyle4.setAlignment(HorizontalAlignment.CENTER);//设置垂直居中

            //设置字体加粗（适用于表名）
            CellStyle cellStyle3 = setDefaultStyle(workbook);
            cellStyle3.setAlignment(HorizontalAlignment.CENTER);//设置垂直居中
            Font font2 = workbook.createFont();
            font2.setBold(true);
            cellStyle3.setFont(font2);

            //合并单元格
            List<Integer> regions = new ArrayList<>();

            List<String> headList = new ArrayList<>();
            headList.add("序号");
            headList.add("是否唯一");
            headList.add("属性名称");
            headList.add("英文名称");
            headList.add("类型");
            headList.add("长度");
            headList.add("精度");
            headList.add("必填");
            headList.add("维护方式");
            headList.add("填写说明");

            //行数
            int rowNumber = 0;
            if (CollectionUtils.isNotEmpty(tableList)) {
                for (int i = 0; i < tableList.size(); i++) {
                    if (i > 0) {
                        rowNumber += 2;
                    }
                    Row row = sheet.createRow(rowNumber); // 空两行
                    regions.add(rowNumber);
                    Cell cell = row.createCell(0);
                    cell.setCellStyle(cellStyle);
                    cell.setCellValue("模型名称");


                    cell = row.createCell(2);
                    cell.setCellValue(tableList.get(i).getName());
                    cell.setCellStyle(cellStyle3);

                    rowNumber++;
                    row = sheet.createRow(rowNumber);
                    regions.add(rowNumber);
                    cell = row.createCell(0);
                    cell.setCellStyle(cellStyle);
                    cell.setCellValue("定义与范围");

                    cell = row.createCell(2);
                    cell.setCellValue(tableList.get(i).getRemark() == null ? tableList.get(i).getCnName() : tableList.get(i).getRemark());
                    cell.setCellStyle(cellStyle4);

                    sheet.removeMergedRegion(1);
                    sheet.removeMergedRegion(0);
                    rowNumber++;
                    row = sheet.createRow(rowNumber);
                    for (int j = 0; j < 10; j++) {
                        cell = row.createCell(j);
                        cell.setCellValue(headList.get(j));
                        cell.setCellStyle(cellStyle);
                    }
                    rowNumber++;

                    String tableId = tableList.get(i).getId();
                    List<BdpColumnDTO> columnDTOList = columnMap.get(tableId);
                    if (CollectionUtils.isNotEmpty(columnDTOList)) {
                        int rowNum = 1;
                        for (BdpColumnDTO bdpColumnDTO : columnDTOList) {
                            row = sheet.createRow(rowNumber);
                            cell = row.createCell(0);
                            cell.setCellValue(rowNum);
                            cell.setCellStyle(cellStyle4);

                            cell = row.createCell(1);
                            cell.setCellValue(bdpColumnDTO.getPrimaryKey() == 1 ? "唯一性" : "");
                            cell.setCellStyle(cellStyle4);

                            cell = row.createCell(2);
                            cell.setCellValue(bdpColumnDTO.getCnName());
                            cell.setCellStyle(cellStyle2);

                            cell = row.createCell(3);
                            cell.setCellValue(bdpColumnDTO.getName());
                            cell.setCellStyle(cellStyle2);

                            cell = row.createCell(4);
                            cell.setCellValue(bdpColumnDTO.getColumnType());
                            cell.setCellStyle(cellStyle4);

                            cell = row.createCell(5);
                            cell.setCellValue(bdpColumnDTO.getColumnLength() == null ? "-" : bdpColumnDTO.getColumnLength().toString());
                            cell.setCellStyle(cellStyle4);

                            cell = row.createCell(6);
                            cell.setCellValue(bdpColumnDTO.getColumnPrecision() == null ? "-" : bdpColumnDTO.getColumnPrecision().toString());
                            cell.setCellStyle(cellStyle4);

                            cell = row.createCell(7);
                            cell.setCellValue(bdpColumnDTO.getNullable() == 0 ? "是" : "");
                            cell.setCellStyle(cellStyle4);

                            cell = row.createCell(8);
                            cell.setCellValue("");
                            cell.setCellStyle(cellStyle4);

                            cell = row.createCell(9);
                            cell.setCellValue("");
                            cell.setCellStyle(cellStyle2);

                            rowNumber++;
                            rowNum++;
                        }
                    }
                }
            }

            //合并单元格
            for (Integer region : regions) {
                sheet.addMergedRegion(new CellRangeAddress(region, region, 0, 1));
                sheet.addMergedRegion(new CellRangeAddress(region, region, 2, 9));
                //合并单元格划线问题
                RegionUtil.setBorderTop(BorderStyle.THIN, new CellRangeAddress(region, region, 0, 1), sheet);
                RegionUtil.setBorderBottom(BorderStyle.THIN, new CellRangeAddress(region, region, 0, 1), sheet);
                RegionUtil.setBorderLeft(BorderStyle.THIN, new CellRangeAddress(region, region, 0, 1), sheet);
                RegionUtil.setBorderRight(BorderStyle.THIN, new CellRangeAddress(region, region, 0, 1), sheet);
                RegionUtil.setBorderTop(BorderStyle.THIN, new CellRangeAddress(region, region, 2, 9), sheet);
                RegionUtil.setBorderBottom(BorderStyle.THIN, new CellRangeAddress(region, region, 2, 9), sheet);
                RegionUtil.setBorderLeft(BorderStyle.THIN, new CellRangeAddress(region, region, 2, 9), sheet);
                RegionUtil.setBorderRight(BorderStyle.THIN, new CellRangeAddress(region, region, 2, 9), sheet);
            }

            sheet.setColumnWidth(0, 3000);
            sheet.setColumnWidth(1, 3000);
            sheet.setColumnWidth(2, 6000);
            sheet.setColumnWidth(3, 6000);
            sheet.setColumnWidth(4, 3000);
            sheet.setColumnWidth(5, 3000);
            sheet.setColumnWidth(6, 3000);
            sheet.setColumnWidth(7, 3000);
            sheet.setColumnWidth(8, 4000);
            sheet.setColumnWidth(9, 12000);
            excelUtils.downLoadExcel("数据模型", workbook, response);

            String logTitle = "导出逻辑模型";
            BdpLogUtil.log("逻辑模型模块", logTitle, PlatformConstant.OpType.select);
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 带边框的样式+
     */
    private CellStyle setDefaultStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        // 边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        return cellStyle;
    }

    /**
     * 导入模型模板
     *
     * @param cover
     * @param file
     * @return
     */
    public String importModelExcel(Integer cover, MultipartFile file) {
        // 返回信息
        String resultInfo = "";
        try {
            // file从前端传过来的 直接接收  或者自己读取一个InputStream
            Workbook wb = new XSSFWorkbook(file.getInputStream());

            // 获取第0个sheet  下标从0开始
            Sheet sheet1 = wb.getSheetAt(0);

            // 导入表的总条数
            int totalCount = sheet1.getLastRowNum();
            // 判断excel是否有数据
            if (totalCount == 0) {
                return "该文件中没有数据或格式不正确，请检查";
            }
            // 失败条数
            int failCount = 0;

            // 失败表集合
            List<ModelExcelDTO> errorTableList = new ArrayList<>();

            Map<String, Map<String, Object>> locationMap = new HashMap<>(); // 存放表位置信息

            // 具有编辑权限分类集合
            List<String> categoryList = newArrayList();
            List<BdpDasCategoryDTO> bdpDasCategoryDTOList = bdpDasCategoryService.findCategoryList();
            if (CollectionUtils.isNotEmpty(bdpDasCategoryDTOList)) {
                String categoryPath = "";
                handleCategorys(bdpDasCategoryDTOList, categoryList, categoryPath);
            }
            for (int i = 1; i <= sheet1.getLastRowNum(); i++) {

                // 表名
                String name = "";

                // 获取第i行数据   下标从0开始   这里i从1开始是因为第0行为字段名 不需要
                Row r = sheet1.getRow(i);

                // 设置第i行的第0列为String类型  不然可能是数字类型
                name = r.getCell(1).getStringCellValue();
                String cnName = r.getCell(2).getStringCellValue();
                String categoryNames = r.getCell(3).getStringCellValue();
                String sheetName = r.getCell(4).getStringCellValue();
                try {
                    // 校验参数
                    validateParam(name, cnName, categoryNames, categoryList);
                    // 处理表信息
                    BdpTableDTO bdpTableDTO = tableHandle(cover, name, cnName, categoryNames, locationMap);
                    if (bdpTableDTO != null && StringUtils.isNotBlank(bdpTableDTO.getId())) {
                        Sheet sheet2 = wb.getSheet(sheetName);
                        if (sheet2 == null) {
                            throw new BusinessException("找不到名称为" + sheetName + "的sheet页");
                        }
                        // 计算表模型高度
                        Integer modelHeight = (sheet2.getLastRowNum() - 1) * 30 + 45;
                        bdpTableDTO.setModelHeight(modelHeight);
                        bdpTableDTO.setModelWidth(modelWidth); // 宽度固定为240

                        List<BdpColumnDTO> allColumnList = new ArrayList<>();
                        for (int j = 1; j <= sheet2.getLastRowNum(); j++) {
                            Row r2 = sheet2.getRow(j);
                            String columnName = r2.getCell(1).getStringCellValue();
                            String columnCnName = r2.getCell(2).getStringCellValue();
                            String columnType = r2.getCell(3).getStringCellValue();
                            int columnLength = (int) r2.getCell(4).getNumericCellValue();
                            int columnPrecision = (int) r2.getCell(5).getNumericCellValue();
                            int primaryKey = (int) r2.getCell(6).getNumericCellValue();
                            int foreignKey = (int) r2.getCell(7).getNumericCellValue();
                            int nullable = (int) r2.getCell(8).getNumericCellValue();
                            int uniqueKey = (int) r2.getCell(9).getNumericCellValue();
                            String remark = r2.getCell(10).getStringCellValue();

                            BdpColumnDTO bdpColumnDTO = new BdpColumnDTO();
                            bdpColumnDTO.setId(ComUtil.getId());
                            bdpColumnDTO.setTableId(bdpTableDTO.getId());
                            bdpColumnDTO.setName(columnName);
                            bdpColumnDTO.setCnName(columnCnName);
                            bdpColumnDTO.setColumnType(columnType);
                            bdpColumnDTO.setColumnLength(columnLength);
                            bdpColumnDTO.setColumnPrecision(columnPrecision);
                            bdpColumnDTO.setNullable(nullable);
                            bdpColumnDTO.setPrimaryKey(primaryKey);
                            bdpColumnDTO.setForeignKey(foreignKey);
                            bdpColumnDTO.setUniqueKey(uniqueKey);
                            bdpColumnDTO.setRemark(remark);
                            bdpColumnDTO.setOrderBy(j);
                            EntityUtils.setCreateAndUpdateInfo(bdpColumnDTO);
                            allColumnList.add(bdpColumnDTO);
                        }
                        // 检查列名
                        validColumnName(allColumnList);
                        List<String> tableIdList = new ArrayList<>();
                        tableIdList.add(bdpTableDTO.getId());
                        // 批量新增
                        batchHandleColumn(tableIdList, allColumnList);
                        // 都成功后再添加表
                        this.insert(bdpTableDTO);
                    }
                } catch (Exception e) {
                    // 存放失败对象
                    ModelExcelDTO modelExcelDTO = new ModelExcelDTO();
                    modelExcelDTO.setName(name);
                    modelExcelDTO.setCnName(cnName);
                    modelExcelDTO.setCategoryNames(categoryNames);
                    modelExcelDTO.setFailInfo(e.getMessage());
                    errorTableList.add(modelExcelDTO);
                    failCount++;
                    e.printStackTrace();
                    continue;
                }
            }
            // 生成错误信息excel
            String filePath = createErrorFile(errorTableList);
            // 成功条数
            int successCount = (totalCount - failCount) < 0 ? 0 : (totalCount - failCount);
            if (failCount == 0) {
                resultInfo = "成功导入" + successCount + "个表";
            } else {
                resultInfo = "成功导入" + successCount + "个表,失败" + failCount + "个表。请在导入结果中查看失败信息。";
            }
            // 记录日志
            insertSysLog(filePath, totalCount, successCount, failCount);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultInfo;
    }

    private void handleCategorys(
            List<BdpDasCategoryDTO> bdpDasCategoryDTOList, List<String> categorys, String categoryPath) {
        for (BdpDasCategoryDTO bdpDasCategoryDTO : bdpDasCategoryDTOList) {
            categoryPath += "/" + bdpDasCategoryDTO.getName();
            if (bdpDasCategoryDTO.getAction() != null && 1 == bdpDasCategoryDTO.getAction()) {
                categorys.add(categoryPath);
                categoryPath = "";
            } else {
                if (CollectionUtils.isNotEmpty(bdpDasCategoryDTO.getChildren())) {
                    handleCategorys(bdpDasCategoryDTO.getChildren(), categorys, categoryPath);
                }
            }
        }
    }

    /**
     * 导入excel校验参数
     *
     * @param name
     * @param cnName
     * @param categoryNames
     */
    private void validateParam(
            String name, String cnName, String categoryNames, List<String> categoryList) {
        if (StringUtils.isBlank(name)) {
            throw new BusinessException("表名不能为空");
        }
        if (StringUtils.isBlank(cnName)) {
            throw new BusinessException("表中文名不能为空");
        }
        if (StringUtils.isBlank(categoryNames)) {
            throw new BusinessException("分类全路径不能为空");
        }
        // 分类权限判断
        if (CollectionUtils.isNotEmpty(categoryList)) {
            BdpDasCategoryDTO bdpDasCategoryDTO = bdpDasCategoryService.selectTopCategory();
            categoryNames = "/" + bdpDasCategoryDTO.getName() + "/" + categoryNames;
            boolean isAuth = false;
            for (String categoryStr : categoryList) {
                if (categoryNames.indexOf(categoryStr) != -1) {
                    isAuth = true;
                    break;
                }
            }
            if (!isAuth) {
                throw new BusinessException("无此分类的修改权限");
            }
        }
    }

    /**
     * 创建错误信息excel
     *
     * @param errorTableList
     * @return
     */
    private String createErrorFile(List<ModelExcelDTO> errorTableList) {
        String filePath = "";
        if (CollectionUtils.isNotEmpty(errorTableList)) {
            List<Map<String, Object>> paramList = getDataList(errorTableList);

            List<ExcelExportEntity> entityList = new ArrayList<>();
            entityList.add(new ExcelExportEntity("表名", "name", 30));
            entityList.add(new ExcelExportEntity("表中文名", "cnName", 30));
            //entityList.add(new ExcelExportEntity("数据库类型", "dataSourceType", 30));
            //entityList.add(new ExcelExportEntity("分类全路径", "categoryNames", 30));
            entityList.add(new ExcelExportEntity("错误信息", "failInfo", 100));

            Workbook workbook =
                    ExcelExportUtil.exportExcel(new ExportParams(null, "EroorData"), entityList, paramList);
            // filePath = "D:\\tmp\\" + System.currentTimeMillis() + "error.xls";
            // 错误文件存储路径
            String dirPath = ConfigUtils.getInstance().getString("system.data.path") + "errorFile/";

            File file = new File(dirPath); // 以某路径实例化一个File对象
            if (!file.exists()) { // 如果不存在
                file.mkdirs(); // 创建目录
            }
            filePath = dirPath + "导入模型" + System.currentTimeMillis() + "error.xls";
            try {
                FileOutputStream output = new FileOutputStream(filePath);
                workbook.write(output); // 写入磁盘
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return filePath;
    }

    private List<Map<String, Object>> getDataList(List<ModelExcelDTO> errorTableList) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ModelExcelDTO modelExcelDTO : errorTableList) {
            Map map = new HashMap();
            map.put("name", modelExcelDTO.getName());
            map.put("cnName", modelExcelDTO.getCnName());
            //map.put("dataSourceType", modelExcelDTO.getDataSourceType());
            //map.put("categoryNames", modelExcelDTO.getCategoryNames());
            map.put("failInfo", modelExcelDTO.getFailInfo());
            list.add(map);
        }

        return list;
    }

    private void insertSysLog(String filePath, int totalCount, int successCount, int failCount) {
        // 记录导入历史
        SysExcelImportHistory sysExcelImportHistory = new SysExcelImportHistory();
        sysExcelImportHistory.setId(ComUtil.getId());
        sysExcelImportHistory.setTotalCount(totalCount);
        sysExcelImportHistory.setSuccessCount(successCount);
        sysExcelImportHistory.setFailCount(failCount);
        sysExcelImportHistory.setSysLookupName("模型导入");
        sysExcelImportHistory.setSysLanguageCode(ThreadContextHelper.getLanguage());
        sysExcelImportHistory.setSysApplication(ThreadContextHelper.getAppId());
        sysExcelImportHistory.setOperatorPerson(ThreadContextHelper.getUserName());

        // 保存异常文件地址
        if (failCount > 0) {
            File file = new File(filePath);
            try {
                InputStream inputStream = new FileInputStream(file);
                String id =
                        sysFileUploadService.doUploadFile(
                                "",
                                inputStream,
                                file.getName(),
                                sysExcelImportHistory.getId(),
                                "",
                                "BDP_DAS_TABLE",
                                ThreadContextHelper.getSecretLevel(),
                                "",
                                "",
                                "",
                                false,
                                "");
                sysExcelImportHistory.setFileUrl(id);
            } catch (Exception e) {
                throw new BusinessException("导入文件失败，errMsg=" + e.getMessage());
            }
        } else {
            sysExcelImportHistory.setFileUrl(avicit.platform6.commons.utils.StringUtils.NULLSTR);
        }
        // 保存历史记录
        sysExcelImportHistoryService.insertSysExcelImportHistory(sysExcelImportHistory);
    }

    /**
     * 导入excel 表的处理
     *
     * @param cover
     * @param name
     * @param cnName
     * @param categoryNames
     * @param locationMap
     * @return
     * @throws Exception
     */
    private BdpTableDTO tableHandle(
            Integer cover,
            String name,
            String cnName,
            String categoryNames,
            Map<String, Map<String, Object>> locationMap)
            throws Exception {
        String tableId = "";
        // 1判断catrgoryNames是否存在,不存在则创建
        String[] categorys = categoryNames.split("/");
        String parentId = "0";
        String categoryId = "";
        for (int i = 0; i < categorys.length; i++) {
            BdpDasCategoryDTO query = new BdpDasCategoryDTO();
            query.setName(categorys[i]);
            query.setParentId(parentId);
            BdpDasCategoryDTO bdpDasCategoryDTO = bdpDasCategoryService.selectOne(query);

            if (bdpDasCategoryDTO == null) {
                bdpDasCategoryDTO = new BdpDasCategoryDTO();
                bdpDasCategoryDTO.setId(ComUtil.getId());
                bdpDasCategoryDTO.setName(categorys[i]);
                bdpDasCategoryDTO.setParentId(parentId);
                bdpDasCategoryDTO.setStatus(StatusEnums.RUNNING.getCode());
                bdpDasCategoryDTO.setCode(getRodomCode(bdpDasCategoryDTO.getId()));
                bdpDasCategoryDTO.setOrderBy(i + 1);
                if (i == categorys.length - 1) {
                    bdpDasCategoryDTO.setLeaf(1);
                } else {
                    bdpDasCategoryDTO.setLeaf(0);
                }
                bdpDasCategoryService.insert(bdpDasCategoryDTO);
                // 添加权限
                // this.commonService.addCategoryPerm(bdpDasCategoryDTO);
            }
            parentId = bdpDasCategoryDTO.getId();
            if (i == categorys.length - 1) {
                categoryId = bdpDasCategoryDTO.getId();
            }
        }
        // 2 判断表是否存在
        BdpTableDTO tableQuery = new BdpTableDTO();
        tableQuery.setName(name);
        tableQuery.setTypeId(categoryId);
        BdpTableDTO bdpTableDTO = bdpDasTableService.selectOne(tableQuery);
        // 3 如果存在 覆盖删除并新增（id不变）
        BdpTableDTO insert = new BdpTableDTO();
        insert.setName(name);
        insert.setCnName(cnName);
        insert.setTypeId(categoryId);
        insert.setType(TableTypeEnum.TABLE_LOGIC.getCode());
        insert.setStatus(DataStateEnum.UNDER_EDITING.getCode());
        if (bdpTableDTO != null) {
            tableId = bdpTableDTO.getId();
            // 覆盖也需要重新计算坐标(2022/10/21  修改为不重新计算坐标)
            if (cover != null && cover == 1) {
                insert.setModelX(bdpTableDTO.getModelX());
                insert.setModelY(bdpTableDTO.getModelY());
                bdpDasLinkService.deleteLinkByTableId(tableId);
                bdpDasTableService.deleteByPrimaryKey(tableId);
                insert.setId(tableId);
                insert.setTableVersion("1.0");
            } else {
                modelSite(locationMap, categoryId, insert);
            }
        }
        // 4 如果不存在直接创建
        if (bdpTableDTO == null) {
            tableId = ComUtil.getId();
            insert.setId(tableId);
            insert.setTableVersion("1.0");
            modelSite(locationMap, categoryId, insert);
        }
        return insert;
    }

    /**
     * 计算坐标
     *
     * @param locationMap
     * @param categoryId
     * @param insert
     * @return
     */
    private void modelSite(
            Map<String, Map<String, Object>> locationMap, String categoryId, BdpTableDTO insert) {
        // 获取缓存的坐标
        Map<String, Object> map =
                locationMap.get(categoryId) == null ? new HashMap<>() : locationMap.get(categoryId);
        // 计算坐标
        countLocation(map, categoryId);

        insert.setModelY(MapUtils.getInteger(map, "modelY"));
        insert.setModelX(MapUtils.getInteger(map, "modelX"));
        locationMap.put(categoryId, map);
    }

    /**
     * 计算坐标
     *
     * @param map
     * @param categoryId
     */
    private void countLocation(Map<String, Object> map, String categoryId) {
        Integer count =
                MapUtils.getInteger(map, "count") == null ? 0 : MapUtils.getInteger(map, "count");
        // 第一个表坐标默认为10,50；
        Integer modelY = 50;
        Integer modelX = 10;
        // 当不换行时，Y坐标不变，横坐标+260
        if (count > 0 && count % 5 != 0) {
            modelY = MapUtils.getInteger(map, "modelY");
            modelX = MapUtils.getInteger(map, "modelX") + 260;
        } else { // 换行时，计算最大y值 + 50 空隙值
            Integer maxY = getModelMaxY(categoryId);
            if (maxY > 0) {
                Integer maxHeigh = getMaxHeigh(categoryId);
                modelY = maxHeigh + 50;
            }
        }
        map.put("modelX", modelX);
        map.put("modelY", modelY);
        map.put("count", count + 1);
    }

    /**
     * 计算y值与高度和最大的表的值
     *
     * @param categoryId
     * @return
     */
    private Integer getMaxHeigh(String categoryId) {
        return this.mapper.getMaxHeigh(categoryId);
    }

    /**
     * 查询此分类下最大y坐标
     *
     * @param categoryId
     * @return
     */
    private Integer getModelMaxY(String categoryId) {
        if (StringUtils.isBlank(categoryId)) {
            throw new BusinessException("请检查参数！");
        }
        // 查询此分类下最大y坐标的值
        Integer maxY = this.mapper.getMaxY(categoryId) == null ? 0 : this.mapper.getMaxY(categoryId);
        return maxY;
    }

    /**
     * 随机生成业务领域分类code
     *
     * @param uuid
     * @return
     */
    private String getRodomCode(String uuid) {
        Random random = new Random();

        String newStr = "";
        for (int i = 0; i < 4; i++) {
            int index = random.nextInt(uuid.length());
            newStr += uuid.charAt(index);
        }
        return newStr.toUpperCase();
    }

    /**
     * 下载模板
     *
     * @param response
     */
    public void downloadModelExcel(HttpServletResponse response) {
        ClassPathResource classPathResource = new ClassPathResource("template/modelTemplate.xlsx");
        InputStream inputStream = null;
        ServletOutputStream servletOutputStream = null;
        try {
            inputStream = classPathResource.getInputStream();
            String filename = "modelTemplate";
            response.setContentType("application/vnd.ms-excel");
            response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.addHeader("charset", "utf-8");
            response.addHeader("Pragma", "no-cache");
            response.setHeader(
                    "Content-Disposition",
                    "attachment;fileName="
                            + new String(filename.getBytes(), StandardCharsets.UTF_8)
                            + ".xlsx");
            servletOutputStream = response.getOutputStream();
            IOUtils.copy(inputStream, servletOutputStream);
            response.flushBuffer();
        } catch (Exception e) {
            throw new BusinessException("下载模板文件错误", e);
        } finally {
            try {
                if (servletOutputStream != null) {
                    servletOutputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /** */

    /**
     * 批量修改分类
     *
     * @return
     */
    public void updateType(Map<String, Object> dataMap) {
        // 导入前校验分类下是否重名
        String errorInfo = this.vilidateSameName(dataMap);
        if (StringUtils.isNotBlank(errorInfo)) {
            throw new BusinessException(errorInfo);
        }
        // 分类id
        String typeId = MapUtils.getString(dataMap, "typeId");
        String projectId = MapUtils.getString(dataMap, "projectId", "");
        // 表id集合
        List<String> tableIds = (List<String>) MapUtils.getObject(dataMap, "tableIds");
        if (CollectionUtils.isNotEmpty(tableIds)) {
            if (StringUtils.isNotBlank(projectId)) {
                this.updateProjectTableTypeId(tableIds, typeId, projectId);
            } else {
                Map<String, Map<String, Object>> locationMap = new HashMap<>(); // 存放表位置信息
                for (String tableId : tableIds) {
                    BdpTableDTO bdpTableDTO = this.selectByPrimaryKey(tableId);

                    // 计算位置
                    // 获取缓存的坐标
                    Map<String, Object> map =
                            locationMap.get(typeId) == null ? new HashMap<>() : locationMap.get(typeId);
                    // 计算坐标
                    countLocation(map, typeId);

                    bdpTableDTO.setModelY(MapUtils.getInteger(map, "modelY"));
                    bdpTableDTO.setModelX(MapUtils.getInteger(map, "modelX"));
                    bdpTableDTO.setTypeId(typeId);
                    this.updateByPrimaryKey(bdpTableDTO);
                    locationMap.put(typeId, map);
                }
            }
        }
        String logTitle = "修改模型分类：【" + JSONObject.toJSONString(dataMap) + "】";
        BdpLogUtil.log("逻辑模型模块", logTitle, PlatformConstant.OpType.select);
    }

    // 批量修改数据空间表管理分类
    private void updateProjectTableTypeId(List<String> tableIds, String typeId, String projectId) {
        for (String tableId : tableIds) {
            this.mapper.updateProjectTableTypeId(projectId, tableId, typeId);
        }
    }

    /**
     * 批量修改分类前校验名称是否重复
     *
     * @return
     */
    private String vilidateSameName(Map map) {
        List<String> tableIdList = (List<String>) map.get("tableIds");
        String typeId = (String) map.get("typeId");
        String projectId = (String) map.get("projectId");
        String errorInfo = "";
        if (StringUtils.isBlank(typeId)) {
            throw new BusinessException("参数typeId不能为空");
        }
        List<BdpTableDTO> errorList = new ArrayList<>();
        for (String tableId : tableIdList) {
            BdpTableDTO bdpTableDTO = this.selectByPrimaryKey(tableId);
            // 工作台表管理判断重名
            if (StringUtils.isNotBlank(projectId)) {
                String oldTypeId = this.mapper.selectTyprIdByTableAndProject(tableId, projectId);
                if (!typeId.equals(oldTypeId)) {
                    List<BdpTableDTO> list =
                            this.mapper.selectTableByProjectAndTypeId(bdpTableDTO.getName(), projectId, typeId);
                    if (CollectionUtils.isNotEmpty(list)) {
                        errorList.add(bdpTableDTO);
                    }
                }
            } else { // 模型管理判断重名
                String oldTypeId = bdpTableDTO.getTypeId();
                if (!typeId.equals(oldTypeId)) {
                    BdpTableDTO query = new BdpTableDTO();
                    query.setTypeId(typeId);
                    query.setName(bdpTableDTO.getName());
                    List<BdpTableDTO> list = this.selectList(query);
                    if (CollectionUtils.isNotEmpty(list)) {
                        errorList.add(bdpTableDTO);
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(errorList)) {
            errorInfo = "以下表在选择分类下存在重复表名，请重新选择:\n";
            for (BdpTableDTO bdpTableDTO : errorList) {
                errorInfo +=
                        "表中文名：【" + bdpTableDTO.getCnName() + "】--表英文名【" + bdpTableDTO.getName() + "】\n";
            }
        }
        return errorInfo;
    }

    /**
     * 末级节点查询模型图形 注意： 1、数据建模，末级节点根据分类节点ID查看模型列表
     *
     * @param typeId typeId
     * @return 模型图形
     */
    @Transactional(readOnly = true)
    public Map<String, Object> searchTableImage(String typeId) {
        Map<String, Object> map = Maps.newHashMap();

        // 查询分类下的表
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        List<TableInfoVO> tableList = qureyTablesByTypeId(typeId, TableTypeEnum.TABLE_LOGIC.getCode(), wordSecretList);
        if (tableList == null || tableList.size() == 0) {
            return null;
        }

        // id集合
        List<String> tableQuery = newArrayList();
        for (TableInfoVO table : tableList) {
            tableQuery.add(table.getId());
        }
        List<ColumnInfoVO> columnInfos = bdpDasColumnService.selectInfoColumns(tableQuery);
        List<PartitionedColumnInfoVO> partitionedColumnInfos =
                columnPartitionedService.selectInfoColumns(tableQuery);
        Map<String, List<ColumnInfoVO>> columnMap = new HashMap<>();
        Map<String, List<PartitionedColumnInfoVO>> partitionedColumnMap = new HashMap<>();
        // 处理字段
        if (CollectionUtils.isNotEmpty(columnInfos)) {
            for (ColumnInfoVO columnInfo : columnInfos) {
                if (columnMap.containsKey(columnInfo.getTableId())) {
                    columnMap.get(columnInfo.getTableId()).add(columnInfo);
                } else {
                    List<ColumnInfoVO> columnInfoVOList = newArrayList();
                    columnInfoVOList.add(columnInfo);
                    columnMap.put(columnInfo.getTableId(), columnInfoVOList);
                }
            }
        }
        // 处理分区字段
        if (CollectionUtils.isNotEmpty(partitionedColumnInfos)) {
            for (PartitionedColumnInfoVO partitionedColumnInfo : partitionedColumnInfos) {
                if (partitionedColumnMap.containsKey(partitionedColumnInfo.getTableId())) {
                    partitionedColumnMap.get(partitionedColumnInfo.getTableId()).add(partitionedColumnInfo);
                } else {
                    List<PartitionedColumnInfoVO> partitionedColumnInfoVOList = newArrayList();
                    partitionedColumnInfoVOList.add(partitionedColumnInfo);
                    partitionedColumnMap.put(partitionedColumnInfo.getTableId(), partitionedColumnInfoVOList);
                }
            }
        }

        for (TableInfoVO table : tableList) {
            // 获取表的字段集合
            if (columnMap.containsKey(table.getId())) {
                table.setColumnList(columnMap.get(table.getId()));
            } else {
                table.setColumnList(newArrayList());
            }
            // 获取表的分区字段集合
            if (partitionedColumnMap.containsKey(table.getId())) {
                table.setPartitionedColumnList(partitionedColumnMap.get(table.getId()));
            } else {
                table.setPartitionedColumnList(newArrayList());
            }
        }
        List<BdpDasLinkDTO> linkList = bdpDasLinkService.searchBdpDasLinkByTableId(tableQuery);
        map.put("tableList", tableList);
        map.put("linkList", linkList);

        String logTitle = "查看逻辑模型";
        BdpLogUtil.log("逻辑模型模块", logTitle, PlatformConstant.OpType.select);
        return map;
    }

    public List<TableInfoVO> qureyTablesByTypeId(String typeId, Integer type, List<String> wordSecretList) {
        return this.mapper.qureyTablesByTypeId(typeId, type, wordSecretList);
    }

    /**
     * 根据id获取表信息以及字段信息
     *
     * @param tableId
     * @return
     */
    public BdpTableDTO getTableById(String tableId, String projectId) {
        BdpTableDTO dasTableDTO = this.selectByPrimaryKey(tableId);
        // 如果是物理模型查看是否有引入逻辑模型
        if (TableTypeEnum.TABLE_PHYSICAL.getCode() == dasTableDTO.getType()) {
            if (StringUtils.isNotBlank(dasTableDTO.getSourceTableId())
                    && dasTableDTO.getSourceType() == 0) {
                BdpTableDTO sourceDTO = this.selectByPrimaryKey(dasTableDTO.getSourceTableId());
                dasTableDTO.setSourceName(sourceDTO.getName());
            }
        }
        // 如果是工作台的表，需要判断导入类型
        if (StringUtils.isNotBlank(projectId)) {
            Integer imported = this.mapper.selectImported(projectId, dasTableDTO.getId(), null);
            dasTableDTO.setImported(imported);
        }
        BdpColumnDTO bdpDasColumnDTO = new BdpColumnDTO();
        bdpDasColumnDTO.setTableId(dasTableDTO.getId());
        List<BdpColumnDTO> columnList =
                bdpDasColumnService.selectList(bdpDasColumnDTO).stream()
                        .sorted(Comparator.comparing(BdpColumnDTO::getOrderBy))
                        .collect(Collectors.toList());
        dasTableDTO.setColumnList(columnList);
        ColumnPartitionedDTO columnPartitionedDTO = new ColumnPartitionedDTO();
        columnPartitionedDTO.setTableId(dasTableDTO.getId());
        List<ColumnPartitionedDTO> columnPartitionedDTOS =
                columnPartitionedService.selectList(columnPartitionedDTO).stream()
                        .sorted(Comparator.comparing(ColumnPartitionedDTO::getOrderBy))
                        .collect(Collectors.toList());
        dasTableDTO.setPartitionedColumnList(columnPartitionedDTOS);
        return dasTableDTO;
    }

    /**
     * 数据授权时，根据授权角色获取具有数据查看权限的模型表
     *
     * @param roleIdList 授权角色
     * @param keyWords   关键字
     * @param action     权限类型
     * @return
     */
    public List<BdpTableDTO> getTableListByRole(
            List<String> roleIdList, String keyWords, Integer action) {
        return this.mapper.getTableListByRole(roleIdList, keyWords, action);
    }

    /**
     * 根据条件分页查询表(逻辑模型)
     *
     * @param type
     * @param status
     * @param keyWords
     * @param pageNo
     * @param pageSize
     * @param typeIdList
     * @param childNodePermMap
     * @param wordSecretList
     * @return
     */
    public Page<BdpTableDTO> qureyTableListByCond(
            Integer type,
            String layerId,
            Integer status,
            String keyWords,
            Integer pageNo,
            Integer pageSize,
            List<String> typeIdList,
            Map<String, Integer> childNodePermMap,
            List<String> wordSecretList) {
        if (CollectionUtils.isEmpty(typeIdList)) {
            return new Page<>();
        }
        if (childNodePermMap == null || childNodePermMap.size() < 1) {
            return new Page<>();
        }

        // step1:如果设置分页查询参数，设置分页
        if (pageNo != null || pageSize != null) {
            com.github.pagehelper.PageHelper.startPage(pageNo, pageSize);
        }

        // step2:分页查询模型列表
        Page<BdpTableDTO> tables = this.mapper.queryTableList(type, layerId, typeIdList, keyWords, status, wordSecretList);
        if (CollectionUtils.isNotEmpty(tables)) {
            for (BdpTableDTO dto : tables) { // 设置表权限（与其分类节点权限绑定，保持一致）
                if (dto == null || StringUtils.isEmpty(dto.getTypeId())) {
                    continue;
                }

                Integer action = childNodePermMap.get(dto.getTypeId());
                if (action == null) {
                    continue;
                }
                if (action == 0) {
                    dto.setActionList(Arrays.asList(0));
                }
                if (action == 1) {
                    dto.setActionList(Arrays.asList(0, 1));
                }
                if (action == 2) {
                    dto.setActionList(Arrays.asList(0, 2));
                }
            }

            valueConvert(tables);
        }

        return tables;
    }

    /**
     * 查询表的列信息
     *
     * @param dataList
     */
    private void tableConvert(Page<BdpTableDTO> dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }

        try {
            List<BdpTableDTO> tableList = dataList.getResult();
            if (tableList != null && tableList.size() > 0) {
                for (BdpTableDTO dasTableDTO : tableList) {
                    // 查询列信息
                    BdpColumnDTO query = new BdpColumnDTO();
                    query.setTableId(dasTableDTO.getId());
                    List<BdpColumnDTO> bdpDasColumnDTOS = bdpDasColumnService.selectList(query);
                    if (CollectionUtils.isNotEmpty(bdpDasColumnDTOS)) {
                        List<BdpColumnDTO> columnList =
                                bdpDasColumnDTOS.stream()
                                        .sorted(Comparator.comparing(BdpColumnDTO::getOrderBy))
                                        .collect(Collectors.toList());
                        dasTableDTO.setColumnList(columnList);
                    }

                    // 查询分区字段
                    ColumnPartitionedDTO partitionedDTO = new ColumnPartitionedDTO();
                    partitionedDTO.setTableId(dasTableDTO.getId());
                    List<ColumnPartitionedDTO> partitionedDTOS =
                            columnPartitionedService.selectList(partitionedDTO);
                    if (CollectionUtils.isNotEmpty(partitionedDTOS)) {
                        List<ColumnPartitionedDTO> columnPartitionedDTOList =
                                partitionedDTOS.stream()
                                        .sorted(Comparator.comparing(ColumnPartitionedDTO::getOrderBy))
                                        .collect(Collectors.toList());
                        dasTableDTO.setPartitionedColumnList(columnPartitionedDTOList);
                    }

                    if (StringUtils.isNotBlank(dasTableDTO.getDataSourceId())) {
                        DataSourceDTO bdpDasDatasourceDTO =
                                bdpDasDatasourceService.selectByPrimaryKey(dasTableDTO.getDataSourceId());
                        if (bdpDasDatasourceDTO == null) {
                            // 处理数据源删除后，表查询出错的问题
                            continue;
                        }
                        dasTableDTO.setBdpDasDatasourceDTO(bdpDasDatasourceDTO);
                        dasTableDTO.setDataSourceName(bdpDasDatasourceDTO.getDatasourceName());
                    }
                }
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 修改状态
     *
     * @param ids
     * @param status
     */
    public void updateStatus(String ids, Integer status) {
        CheckParaUtils.checkStringValidity(ids, logger, "没有传入待启用/停用的ID");

        StringBuffer buf = new StringBuffer();
        String[] idArr = ids.split(Constants.COMMA);
        for (String id : idArr) {
            BdpTableDTO tableDTO = this.selectByPrimaryKey(id);
            CheckParaUtils.checkDbObjectValidity(
                    tableDTO, logger, String.format("没有查到数据，请确保id:%s的模型是否存在", id));
            buf.append(tableDTO.getName()).append(",");

            // 修改状态
            tableDTO.setStatus(status);
            if (status == DataStateEnum.PUBLISHED.getCode()) {
                Double version = tableHistoryService.getMaxVersion(id);
                if (version == null) {
                    version = 1.0;
                } else {
                    version = version + 0.1;
                }
                // 复制到模型历史表
                BdpTableHistoryDTO tableHistoryDTO = new BdpTableHistoryDTO();
                BeanUtils.copyProperties(tableDTO, tableHistoryDTO);
                String tableHistoryId = ComUtil.getId();
                tableHistoryDTO.setId(tableHistoryId);
                tableHistoryDTO.setTableId(id);
                tableHistoryDTO.setTableVersion(version.toString().substring(0, 3));
                tableHistoryService.insert(tableHistoryDTO);
                // 复制字段
                BdpColumnDTO columnQuery = new BdpColumnDTO();
                columnQuery.setTableId(id);
                List<BdpColumnDTO> columnDTOList = bdpDasColumnService.selectList(columnQuery);
                if (CollectionUtils.isNotEmpty(columnDTOList)) {
                    for (BdpColumnDTO bdpColumnDTO : columnDTOList) {
                        BdpColumnHistoryDTO columnHistoryDTO = new BdpColumnHistoryDTO();
                        BeanUtils.copyProperties(bdpColumnDTO, columnHistoryDTO);
                        columnHistoryDTO.setId(ComUtil.getId());
                        columnHistoryDTO.setTableId(tableHistoryId);
                        columnHistoryService.insert(columnHistoryDTO);
                    }
                }
                // 复制分区字段
                ColumnPartitionedDTO partitionedQuery = new ColumnPartitionedDTO();
                partitionedQuery.setTableId(id);
                List<ColumnPartitionedDTO> partitionedDTOList =
                        columnPartitionedService.selectList(partitionedQuery);
                if (CollectionUtils.isNotEmpty(partitionedDTOList)) {
                    for (ColumnPartitionedDTO partitionedDTO : partitionedDTOList) {
                        ColumnPartitionedHistoryDTO partitionedHistoryDTO = new ColumnPartitionedHistoryDTO();
                        BeanUtils.copyProperties(partitionedDTO, partitionedHistoryDTO);
                        partitionedHistoryDTO.setId(ComUtil.getId());
                        partitionedHistoryDTO.setTableId(tableHistoryId);
                        partitionedHistoryService.insert(partitionedHistoryDTO);
                    }
                }
                tableDTO.setTableVersion(version.toString().substring(0, 3));
            }
            this.updateByPrimaryKeySelective(tableDTO);
        }

        // 记录日志
        String logTitle = "";
        if (status == 3) {
            logTitle = "启用模型：【";
        } else {
            logTitle = "停用模型：【";
        }
        logTitle += buf.toString() + "】";
        BdpLogUtil.log("逻辑模型模块", logTitle, PlatformConstant.OpType.update);
    }

    /**
     * public void cancelDB(Map<String, String> map) { String tableId = map.get("tableId"); if
     * (StringUtils.isBlank(tableId)) { throw new BusinessException("请检查参数"); } BdpTableDTO
     * dasTableDTO = this.selectByPrimaryKey(tableId); if
     * (TableTypeEnum.TABLE_GLOBAL_MODELING.getCode() == dasTableDTO.getType()) { // 查询引用模型的数据空间
     * List<String> projectNames = this.mapper.getProjectNamesByTableId(tableId); if
     * (CollectionUtils.isNotEmpty(projectNames)) { StringBuffer sb = new StringBuffer(); for (String
     * str : projectNames) { sb.append(str).append("、"); } String projectNameStr =
     * sb.deleteCharAt(sb.length() - 1).toString(); throw new BusinessException(projectNameStr +
     * "引用了本模型，请先移除空间里模型引用!"); } } dasTableDTO.setStoreStatus(0);
     * this.updateByPrimaryKey(dasTableDTO); }*
     */

    /**
     * @物理模型导入逻辑模型 @参数 @返回值
     */
    public BdpTableDTO importLogicModel(String sourceTableId) {
        BdpTableDTO bdpTableDTO = this.selectByPrimaryKey(sourceTableId);
        if (bdpTableDTO == null) {
            throw new BusinessException("查询对象为null");
        }
        List<String> tableQuery = newArrayList();
        tableQuery.add(sourceTableId);
        List<BdpColumnDTO> columnDTOS = bdpDasColumnService.searchByTableId(tableQuery);
        /**
         * if(CollectionUtils.isNotEmpty(columnDTOS)){ BaseDBAdapter dbAdapter =
         * DbAdapterUtils.getDbAdapter(bdpTableDTO.getDataSourceType()); try { for (BdpColumnDTO
         * columnDTO : columnDTOS) { Integer javeType = DBUtils.getJavaType(columnDTO.getColumnType());
         * String sqlType = dbAdapter.convertDbType(javeType); columnDTO.setColumnType(sqlType); } }
         * catch (Exception e) { e.printStackTrace(); } }*
         */
        BdpTableDTO physicalTableDTO = new BdpTableDTO();
        BeanUtils.copyProperties(bdpTableDTO, physicalTableDTO);
        // physicalTableDTO.setType(5);//物理模型
        physicalTableDTO.setColumnList(columnDTOS);
        return physicalTableDTO;
    }

    /**
     * @逻辑模型导入物理模型 @参数 @返回值
     */
    public List<String> importPhysicalModel(String sourceTableIds, String typeId) {
        List<String> resultIds = Lists.newArrayList();
        CheckParaUtils.checkStringValidity(sourceTableIds, logger, "id参数为空");
        CheckParaUtils.checkStringValidity(typeId, logger, "主题参数为空");
        String[] idArr = sourceTableIds.split(Constants.COMMA);
        for (String sourceTableId : idArr) {
            try {
                BdpTableDTO physicalTable = this.selectByPrimaryKey(sourceTableId);
                if (physicalTable == null) {
                    throw new BusinessException("查询对象为null");
                }
                List<BdpTableDTO> list =
                        mapper.selectByNameAndTypeId(
                                typeId, physicalTable.getName().toLowerCase(), TableTypeEnum.TABLE_LOGIC.getCode());
                if (CollectionUtils.isNotEmpty(list)) {
                    throw new BusinessException("导入失败:模型重名");
                }
                List<String> tableQuery = newArrayList();
                tableQuery.add(sourceTableId);
                List<BdpColumnDTO> columnDTOS = bdpDasColumnService.searchByTableId(tableQuery);
                // 新模型的id
                String logicTableId = ComUtil.getId();
                if (CollectionUtils.isNotEmpty(columnDTOS)) {
                    BaseDBAdapter dbAdapter = DbAdapterUtils.getDbAdapter(physicalTable.getDataSourceType());

                    for (BdpColumnDTO columnDTO : columnDTOS) {
                        // iotdb time字段不导入
                        if (Constants.DB_TYPE_IOTDB.equals(physicalTable.getDataSourceType())
                                && "time".equals(columnDTO.getName().toLowerCase())
                                && "timestamp".equals(columnDTO.getColumnType())) {
                            continue;
                        }
                        Integer javaType = dbAdapter.convertJavaType(columnDTO.getColumnType());
                        String columnType = DBUtils.getJavaTypeName(javaType);
                        columnDTO.setColumnType(columnType);
                        columnDTO.setTableId(logicTableId);
                        columnDTO.setId(ComUtil.getId());
                        bdpDasColumnService.insertBdpDasColumn(columnDTO);
                    }
                }
                BdpTableDTO logicTableDTO = new BdpTableDTO();
                BeanUtils.copyProperties(physicalTable, logicTableDTO);

                logicTableDTO.setId(logicTableId);
                logicTableDTO.setDataSourceType(null);
                logicTableDTO.setDataSourceId(null);
                logicTableDTO.setTableVersion("1.0");
                logicTableDTO.setTypeId(typeId);
                logicTableDTO.setStatus(0);
                logicTableDTO.setType(TableTypeEnum.TABLE_LOGIC.getCode());
                logicTableDTO.setSourceTableId(sourceTableId);
                logicTableDTO.setSourceType(1);

                // 计算表模型高度
                Integer modelHeight = columnDTOS.size() * 30 + 45;
                logicTableDTO.setModelHeight(modelHeight);
                logicTableDTO.setModelWidth(modelWidth); // 宽度固定为240
                // 计算坐标
                Map<String, Map<String, Object>> locationMap = new HashMap<>(); // 存放表位置信息
                modelSite(locationMap, typeId, logicTableDTO);
                this.insert(logicTableDTO);
                resultIds.add(logicTableId);
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        return resultIds;
    }

    public List<BdpColumnDTO> changeColumnType(String sourceTableId, String dataSourceType) {
        List<String> tableQuery = newArrayList();
        tableQuery.add(sourceTableId);
        List<BdpColumnDTO> columnDTOS = bdpDasColumnService.searchByTableId(tableQuery);
        if (CollectionUtils.isNotEmpty(columnDTOS)) {
            BaseDBAdapter dbAdapter = DbAdapterUtils.getDbAdapter(dataSourceType);
            try {
                for (BdpColumnDTO columnDTO : columnDTOS) {
                    columnDTO.setId("");
                    Integer javeType = DBUtils.getJavaType(columnDTO.getColumnType());
                    String sqlType = dbAdapter.convertDbType(javeType);
                    //sqlserver 长度需要特殊处理
                    if("sqlserver".equals(dataSourceType)){
                        if(sqlserverColTypeList().contains(sqlType.toLowerCase())){
                            columnDTO.setColumnLength(null);
                        }
                    }
                    columnDTO.setColumnType(sqlType);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return columnDTOS;
    }

    /**
     * 模型版本对比 @参数 @返回值
     */
    public Map<String, Object> compareTableVersion(String leftTableId, String rightTableId) {
        Map<String, Object> map = new HashMap<>();
        BdpTableHistoryDTO leftTable = tableHistoryService.getHistoryTableById(leftTableId);
        BdpTableHistoryDTO rightTable = tableHistoryService.getHistoryTableById(rightTableId);
        // 返回两个版本模型对象
    /*List<BdpTableHistoryDTO> historyTableList = newArrayList();
    historyTableList.add(leftTable);
    historyTableList.add(rightTable);
    map.put("tableList", historyTableList);*/
        // 对比模型信息
        Map<String, Object> baseInfo = this.diffProperty(leftTable, rightTable);
        map.put("baseInfo", baseInfo);
        // 对比字段
        BdpColumnHistoryDTO leftQuery = new BdpColumnHistoryDTO();
        leftQuery.setTableId(leftTableId);
        List<BdpColumnHistoryDTO> leftColumns = columnHistoryService.selectList(leftQuery);
        BdpColumnHistoryDTO rightQuery = new BdpColumnHistoryDTO();
        rightQuery.setTableId(rightTableId);
        List<BdpColumnHistoryDTO> rightColumns = columnHistoryService.selectList(rightQuery);
        diffColumn(
                leftTable.getTableVersion(), rightTable.getTableVersion(), leftColumns, rightColumns, map);
        return map;
    }

    private Map<String, Object> diffProperty(
            BdpTableHistoryDTO leftTable, BdpTableHistoryDTO rightTable) {
        Map<String, Object> map = Maps.newHashMap();
        // 版本
        Map<String, Object> versionMap = Maps.newHashMap();
        versionMap.put("left", "v" + leftTable.getTableVersion());
        versionMap.put("right", "v" + rightTable.getTableVersion());
        map.put("version", versionMap);
        // 中文名
        Map<String, Object> cnNameMap =
                this.compareProperty(leftTable.getCnName(), rightTable.getCnName());
        map.put("cnName", cnNameMap);
        // 英文名
        Map<String, Object> nameMap = this.compareProperty(leftTable.getName(), rightTable.getName());
        map.put("name", nameMap);
        // 所属主题
        Map<String, Object> typeNameMap =
                this.compareProperty(leftTable.getTypeName(), rightTable.getTypeName());
        map.put("typeName", typeNameMap);
        // 所属分层
        Map<String, Object> layerNameMap =
                this.compareProperty(leftTable.getLayerName(), rightTable.getLayerName());
        map.put("layerName", layerNameMap);
        // 备注
        Map<String, Object> remarkMap =
                this.compareProperty(leftTable.getRemark(), rightTable.getRemark());
        map.put("remark", remarkMap);
        return map;
    }

    private Map<String, Object> compareProperty(Object left, Object right) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("left", left == null ? "" : left);
        map.put("right", right == null ? "" : right);
        if (!Objects.equals(left, right)) {
            map.put("diff", true);
        } else {
            map.put("diff", false);
        }
        return map;
    }

    private void diffColumn(
            String leftVersion,
            String rightVersion,
            List<BdpColumnHistoryDTO> leftColumns,
            List<BdpColumnHistoryDTO> rightColumns,
            Map<String, Object> map) {
        if (CollectionUtils.isEmpty(leftColumns) || CollectionUtils.isEmpty(rightColumns)) {
            throw new BusinessException("字段为空，清检查！");
        }

        // 1.list转换为map，便于比较
        Map<String, BdpColumnHistoryDTO> leftColumnMap = Maps.newHashMap();
        Map<String, BdpColumnHistoryDTO> rightColumnMap = Maps.newHashMap();
        // 2.存放key值list
        List<String> leftNameList = Lists.newArrayList();
        List<String> rightNameList = Lists.newArrayList();

        for (BdpColumnHistoryDTO leftColumn : leftColumns) {
            leftColumnMap.put(leftColumn.getName(), leftColumn);
            leftNameList.add(leftColumn.getName());
        }
        for (BdpColumnHistoryDTO rightColumn : rightColumns) {
            rightColumnMap.put(rightColumn.getName(), rightColumn);
            rightNameList.add(rightColumn.getName());
        }

        // 3.比较key值
        // 左表多的字段名称
        List<String> leftAddList =
                leftNameList.stream()
                        .filter(element -> !rightNameList.contains(element))
                        .collect(Collectors.toList());
        // 右表多的字段名称
        List<String> rightAddList =
                rightNameList.stream()
                        .filter(element -> !leftNameList.contains(element))
                        .collect(Collectors.toList());
        // 相同字段名称
        List<String> sameKeyList =
                leftNameList.stream()
                        .filter(element -> rightNameList.contains(element))
                        .collect(Collectors.toList());

        // 无差异字段集合
        List<BdpColumnHistoryDTO> columnList = Lists.newArrayList();
        // 有差异字段集合
        List<Map<String, Object>> diffColumnList = Lists.newArrayList();
        // 字段是否全部相同标识
        for (String sameKey : sameKeyList) {
            BdpColumnHistoryDTO leftDTO = leftColumnMap.get(sameKey);
            BdpColumnHistoryDTO rightDTO = rightColumnMap.get(sameKey);
            boolean sameFlag = compareColumnValue(leftDTO, rightDTO);
            if (sameFlag) { // 无变化字段
                columnList.add(leftDTO);
            } else {
                Map<String, Object> diffValueMap =
                        handleChangeColumn(leftVersion, rightVersion, leftDTO, rightDTO);
                diffColumnList.add(diffValueMap);
            }
        }

        // 处理左表匹配不上字段
        for (String leftAddName : leftAddList) {
            BdpColumnHistoryDTO leftAdd = leftColumnMap.get(leftAddName);
            Map<String, Object> diffValueMap =
                    handleChangeColumn(leftVersion, rightVersion, leftAdd, null);
            diffColumnList.add(diffValueMap);
        }

        // 处理右表匹配不上字段
        for (String rightAddName : rightAddList) {
            BdpColumnHistoryDTO rightAdd = rightColumnMap.get(rightAddName);
            Map<String, Object> diffValueMap =
                    handleChangeColumn(leftVersion, rightVersion, null, rightAdd);
            diffColumnList.add(diffValueMap);
        }

        if (CollectionUtils.isNotEmpty(columnList)) {
            map.put("columnList", columnList);
        }
        if (CollectionUtils.isNotEmpty(diffColumnList)) {
            map.put("diffColumnList", diffColumnList);
        }
    }

    private Map<String, Object> handleChangeColumn(
            String leftVersion,
            String rightVersion,
            BdpColumnHistoryDTO leftDTO,
            BdpColumnHistoryDTO rightDTO) {
        Map<String, Object> map = Maps.newHashMap();
        // 版本
        Map<String, Object> versionMap = Maps.newHashMap();
        versionMap.put("left", "v" + leftVersion);
        versionMap.put("right", "v" + rightVersion);
        map.put("version", versionMap);
        // 英文名
        Map<String, Object> nameMap;
        if (leftDTO == null) {
            nameMap = this.compareProperty("", rightDTO.getName());
        } else if (rightDTO == null) {
            nameMap = this.compareProperty(leftDTO.getName(), "");
        } else {
            nameMap = this.compareProperty(leftDTO.getName(), rightDTO.getName());
        }
        map.put("name", nameMap);
        // 中文名
        Map<String, Object> cnNameMap;
        if (leftDTO == null) {
            cnNameMap = this.compareProperty("", rightDTO.getCnName());
        } else if (rightDTO == null) {
            cnNameMap = this.compareProperty(leftDTO.getCnName(), "");
        } else {
            cnNameMap = this.compareProperty(leftDTO.getCnName(), rightDTO.getCnName());
        }
        map.put("cnName", cnNameMap);
        // 类型
        Map<String, Object> columnTypeMap;
        if (leftDTO == null) {
            columnTypeMap = this.compareProperty("", rightDTO.getColumnType());
        } else if (rightDTO == null) {
            columnTypeMap = this.compareProperty(leftDTO.getColumnType(), "");
        } else {
            columnTypeMap = this.compareProperty(leftDTO.getColumnType(), rightDTO.getColumnType());
        }
        map.put("columnType", columnTypeMap);
        // 长度
        Map<String, Object> columnLengthMap;
        if (leftDTO == null) {
            columnLengthMap = this.compareProperty("", rightDTO.getColumnLength());
        } else if (rightDTO == null) {
            columnLengthMap = this.compareProperty(leftDTO.getColumnLength(), "");
        } else {
            columnLengthMap = this.compareProperty(leftDTO.getColumnLength(), rightDTO.getColumnLength());
        }
        map.put("columnLength", columnLengthMap);
        // 精度
        Map<String, Object> columnPrecisionMap;
        if (leftDTO == null) {
            columnPrecisionMap = this.compareProperty("", rightDTO.getColumnPrecision());
        } else if (rightDTO == null) {
            columnPrecisionMap = this.compareProperty(leftDTO.getColumnPrecision(), "");
        } else {
            columnPrecisionMap =
                    this.compareProperty(leftDTO.getColumnPrecision(), rightDTO.getColumnPrecision());
        }
        map.put("columnPrecision", columnPrecisionMap);
        // 主键
        Map<String, Object> primaryKeyMap;
        if (leftDTO == null) {
            primaryKeyMap = this.compareProperty("", rightDTO.getPrimaryKey());
        } else if (rightDTO == null) {
            primaryKeyMap = this.compareProperty(leftDTO.getPrimaryKey(), "");
        } else {
            primaryKeyMap = this.compareProperty(leftDTO.getPrimaryKey(), rightDTO.getPrimaryKey());
        }
        map.put("primaryKey", primaryKeyMap);
        // 外键
        Map<String, Object> foreignKeyMap;
        if (leftDTO == null) {
            foreignKeyMap = this.compareProperty("", rightDTO.getForeignKey());
        } else if (rightDTO == null) {
            foreignKeyMap = this.compareProperty(leftDTO.getForeignKey(), "");
        } else {
            foreignKeyMap = this.compareProperty(leftDTO.getForeignKey(), rightDTO.getForeignKey());
        }
        map.put("foreignKey", foreignKeyMap);
        // 唯一
        Map<String, Object> uniqueKeyMap;
        if (leftDTO == null) {
            uniqueKeyMap = this.compareProperty("", rightDTO.getUniqueKey());
        } else if (rightDTO == null) {
            uniqueKeyMap = this.compareProperty(leftDTO.getUniqueKey(), "");
        } else {
            uniqueKeyMap = this.compareProperty(leftDTO.getUniqueKey(), rightDTO.getUniqueKey());
        }
        map.put("uniqueKey", uniqueKeyMap);
        // 为空
        Map<String, Object> nullableMap;
        if (leftDTO == null) {
            nullableMap = this.compareProperty("", rightDTO.getNullable());
        } else if (rightDTO == null) {
            nullableMap = this.compareProperty(leftDTO.getNullable(), "");
        } else {
            nullableMap = this.compareProperty(leftDTO.getNullable(), rightDTO.getNullable());
        }
        map.put("nullable", nullableMap);
        // 备注
        Map<String, Object> remarkMap;
        if (leftDTO == null) {
            remarkMap = this.compareProperty("", rightDTO.getRemark());
        } else if (rightDTO == null) {
            remarkMap = this.compareProperty(leftDTO.getRemark(), "");
        } else {
            remarkMap = this.compareProperty(leftDTO.getRemark(), rightDTO.getRemark());
        }
        map.put("remark", remarkMap);

        return map;
    }

    // 比较字段值
    private boolean compareColumnValue(BdpColumnHistoryDTO leftDTO, BdpColumnHistoryDTO rightDTO) {
        if (!Objects.equals(leftDTO.getCnName(), rightDTO.getCnName())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getColumnType(), rightDTO.getColumnType())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getColumnLength(), rightDTO.getColumnLength())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getColumnPrecision(), rightDTO.getColumnPrecision())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getPrimaryKey(), rightDTO.getPrimaryKey())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getForeignKey(), rightDTO.getForeignKey())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getUniqueKey(), rightDTO.getUniqueKey())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getNullable(), rightDTO.getNullable())) {
            return false;
        }
        if (!Objects.equals(leftDTO.getRemark(), rightDTO.getRemark())) {
            return false;
        }
        return true;
    }

    private boolean isSameAndContainsNull(String str1, String str2) {
        if (Objects.isNull(str1) || Objects.isNull(str2)) {
            return false;
        }
        return false;
    }

    public List<BdpColumnDTO> physicalChangeColumnType(
            List<Map<String, Object>> columns, String dataSourceType) {
        List<BdpColumnDTO> columnDTOS = Lists.newArrayList();
        try {

            for (Map<String, Object> column : columns) {
                BdpColumnDTO bdpColumnDTO = new BdpColumnDTO();
                // 字段类型
                String columnType = (String) column.get("dataTypeString");
                BaseDBAdapter dbAdapter = DbAdapterUtils.getDbAdapter(dataSourceType);
                Integer javeType = DBUtils.getJavaType(columnType);
                bdpColumnDTO.setColumnType(dbAdapter.convertDbType(javeType));
                // 字段名
                bdpColumnDTO.setName((String) column.get("enName"));
                // 中文名
                bdpColumnDTO.setCnName((String) column.get("name"));
                // 标准字段id
                bdpColumnDTO.setStandardId((String) column.get("id"));
                //长度
                if (column.get("length") != null) {
                    bdpColumnDTO.setColumnLength((Integer) column.get("length"));
                }
                //精度
                if (column.get("decimalPrecision") != null) {
                    bdpColumnDTO.setColumnPrecision((Integer) column.get("decimalPrecision"));
                }
                //非空
                if (column.get("notNull") != null) {
                    bdpColumnDTO.setNullable((Integer) column.get("notNull") == 1 ? 0 : 1);
                } else {
                    bdpColumnDTO.setNullable(1);
                }
                //唯一
                if (column.get("uniqueKey") != null) {
                    bdpColumnDTO.setUniqueKey((Integer) column.get("uniqueKey"));
                } else {
                    bdpColumnDTO.setUniqueKey(0);
                }
                columnDTOS.add(bdpColumnDTO);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return columnDTOS;
    }

    public List<String> importMetadataTable(String sourceTableIds, Integer modelType, String typeId) {
        List<String> resultIds = Lists.newArrayList();
        try {
            CheckParaUtils.checkStringValidity(sourceTableIds, logger, "id参数为空");
            CheckParaUtils.checkIntegerValidity(modelType, logger, "模型类型为空");
            CheckParaUtils.checkStringValidity(typeId, logger, "主题参数为空");

            Map<String, Map<String, Object>> locationMap = new HashMap<>(); // 存放表位置信息

            String[] idArr = sourceTableIds.split(Constants.COMMA);
            for (String historyTableId : idArr) {
                BdpTableHistoryDTO historyDTO = tableHistoryService.selectByPrimaryKey(historyTableId);
                BdpTableDTO bdpTableDTO = new BdpTableDTO();
                BeanUtils.copyProperties(historyDTO, bdpTableDTO);
                String tableId = ComUtil.getId();
                bdpTableDTO.setSecretLevel(historyDTO.getSecretLevel());
                bdpTableDTO.setTableVersion("1.0");
                bdpTableDTO.setType(modelType);
                bdpTableDTO.setTypeId(typeId);
                bdpTableDTO.setSourceType(2); // 元数据
                bdpTableDTO.setSourceTableId(historyTableId);
                bdpTableDTO.setId(tableId);
                if (TableTypeEnum.TABLE_LOGIC.getCode() == modelType) {
                    bdpTableDTO.setStatus(DataStateEnum.UNDER_EDITING.getCode());
                } else {
                    bdpTableDTO.setStatus(DataStateEnum.PUBLISHED.getCode());
                    bdpTableDTO.setDataSourceId(historyDTO.getDataSourceId());
                    bdpTableDTO.setDataSourceType(historyDTO.getDataSourceType());
                }

                // 字段信息
                BdpColumnHistoryDTO columnHistoryQuery = new BdpColumnHistoryDTO();
                columnHistoryQuery.setTableId(historyTableId);
                List<BdpColumnHistoryDTO> columnVos = columnHistoryService.selectList(columnHistoryQuery);
                if (CollectionUtils.isEmpty(columnVos)) {
                    throw new BusinessException("元数据字段为空，请检查！");
                }

                if (TableTypeEnum.TABLE_LOGIC.getCode() == modelType) { // 逻辑模型计算位置
                    modelSite(locationMap, typeId, bdpTableDTO);

                    bdpTableDTO.setModelWidth(modelWidth);
                    bdpTableDTO.setModelHeight(columnVos.size() * 30 + 45);
                }

                List<BdpColumnDTO> allColumnList = new ArrayList<>();
                for (BdpColumnHistoryDTO columnVo : columnVos) {
                    if (TableTypeEnum.TABLE_LOGIC.getCode() == modelType) {
                        // 逻辑模型iotdb time字段不导入
                        if (Constants.DB_TYPE_IOTDB.equals(historyDTO.getDataSourceType())
                                && "time".equals(columnVo.getName().toLowerCase())
                                && "timestamp".equals(columnVo.getColumnType())) {
                            continue;
                        }
                    }
                    BdpColumnDTO bdpColumnDTO = new BdpColumnDTO();
                    BeanUtils.copyProperties(columnVo, bdpColumnDTO);

                    bdpColumnDTO.setId(ComUtil.getId());
                    bdpColumnDTO.setTableId(bdpTableDTO.getId());
                    if (TableTypeEnum.TABLE_LOGIC.getCode() == modelType) { // 逻辑模型需要转换字段类型
                        // 字段类型
                        String columnType = columnVo.getColumnType();
                        BaseDBAdapter dbAdapter = DbAdapterUtils.getDbAdapter(historyDTO.getDataSourceType());
                        Integer javaType = dbAdapter.convertJavaType(columnType);
                        bdpColumnDTO.setColumnType(DBUtils.getJavaTypeName(javaType));
                    }
                    EntityUtils.setCreateAndUpdateInfo(bdpColumnDTO);
                    allColumnList.add(bdpColumnDTO);
                }

                // 分区信息
                ColumnPartitionedHistoryDTO columnPartitionedHistoryQuery =
                        new ColumnPartitionedHistoryDTO();
                columnPartitionedHistoryQuery.setTableId(historyTableId);
                List<ColumnPartitionedHistoryDTO> columnPartitioneds =
                        partitionedHistoryService.selectList(columnPartitionedHistoryQuery);

                if (CollectionUtils.isNotEmpty(columnPartitioneds)
                        && TableTypeEnum.TABLE_PHYSICAL.getCode() == modelType) {
                    List<ColumnPartitionedDTO> allColumnPartitionedList = new ArrayList<>();
                    for (ColumnPartitionedHistoryDTO columnPartitioned : columnPartitioneds) {
                        ColumnPartitionedDTO columnPartitionedDTO = new ColumnPartitionedDTO();
                        BeanUtils.copyProperties(columnPartitioned, columnPartitionedDTO);
                        columnPartitionedDTO.setId(ComUtil.getId());
                        columnPartitionedDTO.setTableId(bdpTableDTO.getId());
                        allColumnPartitionedList.add(columnPartitionedDTO);
                    }
                    // 新增分区字段
                    columnPartitionedService.deleteByTableId(bdpTableDTO.getId());
                    columnPartitionedService.insertListByBatch(allColumnPartitionedList);
                }

                // 检查列名
                validColumnName(allColumnList);
                List<String> tableIdList = new ArrayList<>();
                tableIdList.add(bdpTableDTO.getId());
                // 批量新增字段
                batchHandleColumn(tableIdList, allColumnList);

                // 都成功后再添加表
                this.insert(bdpTableDTO);
                resultIds.add(tableId);

                String logTitle = "元数据导入：【" + JSONObject.toJSONString(bdpTableDTO) + "】";
                BdpLogUtil.log("物理模型模块", logTitle, PlatformConstant.OpType.insert);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultIds;
    }

    public QueryRespBean<BdpTableDTO> searchImportList(
            String typeId,
            String datasourceId,
            Integer type,
            Integer importType,
            String sourceTypeId,
            String keyWords,
            Integer pageNo,
            Integer pageSize) {
        QueryRespBean<BdpTableDTO> queryRespBean = new QueryRespBean<>();
        Page<BdpTableDTO> tables = null;
        // 如果导入到逻辑模型
        if (TableTypeEnum.TABLE_LOGIC.getCode() == importType) {
            List<String> roleIdList =
                    this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
            List<String> typeIdList = new ArrayList<>();
            Map<String, Integer> childNodePermMap =
                    this.bdpDasCategoryService.getChildNodeMapWithPerm(typeId, roleIdList);
            if (childNodePermMap != null && childNodePermMap.size() > 0) {
                typeIdList = childNodePermMap.keySet().stream().collect(Collectors.toList());
            }

            com.github.pagehelper.PageHelper.startPage(pageNo, pageSize);
            if (TableTypeEnum.TABLE_PHYSICAL.getCode() == type) { // 物理模型导入到逻辑模型
                tables = this.mapper.searchImportPhysicalList(typeIdList, sourceTypeId, keyWords);
            }
            if (TableTypeEnum.TABLE_METADATA.getCode() == type) {
                tables = this.mapper.searchImportMetaDataList(datasourceId, sourceTypeId, keyWords);
            }
        } else { // 物理模型导入元数据
            tables = this.mapper.searchImportMetaDatas(datasourceId, keyWords);
        }
        // 处理权限
        // handleLimits(tables,sourceTypeId);
        queryRespBean.setResult(tables);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    private void handleLimits(Page<BdpTableDTO> tables, String sourceTypeId) {
        List<String> roleIdList =
                this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
        Map<String, Integer> childNodePermMap =
                this.bdpDasCategoryService.getChildNodeMapWithPerm(sourceTypeId, roleIdList);
        if (CollectionUtils.isNotEmpty(tables)) {
            for (BdpTableDTO dto : tables) { // 设置表权限（与其分类节点权限绑定，保持一致）
                if (dto == null || StringUtils.isEmpty(dto.getTypeId())) {
                    continue;
                }

                Integer action = childNodePermMap.get(dto.getTypeId());
                if (action == null) {
                    continue;
                }
                if (action == 0) {
                    dto.setActionList(Arrays.asList(0));
                }
                if (action == 1) {
                    dto.setActionList(Arrays.asList(0, 1));
                }
                if (action == 2) {
                    dto.setActionList(Arrays.asList(0, 2));
                }
            }
        }
    }


    private List<String> sqlserverColTypeList(){
        List<String> list = new ArrayList<>();
        list.add("bit");
        list.add("tinyint");
        list.add("smallint");
        list.add("int");
        list.add("real");
        return list;
    }

}
